preventDefault, stopPropagation, stopImmediatePropagation 三者的區別

event事件對象有三種易混淆的方法,本文講述他們之間的區別:javascript

  • Event.preventDefault()
  • Event.stopPropagation()
  • Event.stopImmediatePropagation()

綜述

首先,咱們看看他們在MDN上的介紹:html

  • preventDefault: 若是當前event.cancelable屬性爲true,則取消的當前事件的默認動做,但不阻止當前事件的進一步傳播
  • stopPropagation: 阻止當前冒泡或捕獲階段的進一步傳播
  • stopImmediatePropagation: 阻止調用相同事件的其餘監聽器

Event.preventDefault

咱們來看一個代碼示例,當點擊一個form中的submit按鈕時會將form提交處理,此時若是使用Event.preventDefault,就能夠在點擊submit按鈕時避免表格提交。java

<form id="myForm" action="/my-handling-form-page" method="post">
    <div>
        <label for="name">姓名:</label>
        <input type="text" id="name" />
    </div>
    <div>
        <label for="mail">電子郵箱:</label>
        <input type="email" id="mail" />
    </div>
    <div>
        <label for="msg">消息:</label>
        <textarea id="msg"></textarea>
    </div>
    
    <div class="button">
        <button type="submit">發送你的消息</button>
    </div>
</form>
$('#myForm').on('submit', function(e) {
    e.preventDefault(); // 什麼都不會發生
});

Event.preventDefault能確保表格不會被提交,但他不能阻止來自冒泡階段的submit或點擊事件,其餘兩種方法就是解決這個問題的。post

Event.stopPropagation

stopPropagation 保證當前事件再也不進一步冒泡,經過如下代碼示例說明:網站

<div class="container">
    <a href="#" class="element">點擊我!</a>
</div>
$('.container').on('click', function(e) {
    console.log('container 被點擊了');
});

$('.element').on('click', function(e) {
    e.preventDefault(); // 此時連接不會跳轉
    console.log('element 被點擊了');
});

此時點擊連接,console會顯示:code

"element 被點擊了"
"container 被點擊了"

這時若是添加Event.stopPropagation:orm

$('.container').on('click', function(e) {
    console.log('container 被點擊了');
});

$('.element').on('click', function(e) {
    e.preventDefault(); // 此時連接不會跳轉
    e.stopPropagation(); // 此時事件冒泡被阻止
    console.log('element 被點擊了');
});

再次點擊連接,會看到:htm

"element 被點擊了"

Event.stopImmediatePropagation

以上兩種方法已經能夠解決咱們在事件處理中90%的問題,接下來介紹一種沒法解決情形。
一樣是使用上面的示例,但此次咱們給<a/>添加2個class,一個是被全部<a/>共享的class: item,另外一個是獨有的class: element,假設這兩個class對當前網站的功能很重要。對象

<div class="container">
    <a href="#" class="item element">Click Me!</a>
</div>

咱們首先使用以前提到的Event.stopPropagation事件

$('.element').on('click', function(e) {
    e.preventDefault(); // 此時連接不會跳轉
    e.stopPropagation(); // 此時事件冒泡被阻止
    console.log('element 被點擊了');
});

$('.item').on('click', function(e) {
    console.log('item 被點擊了');
});

當咱們點擊<a/>時,將會顯示:

"item 被點擊了"
"element 被點擊了"

這個現象會發生是由於item與element在DOM中是被平等對待的,與以前<a/>被點擊而後冒泡到父級div不一樣,此次咱們點擊同時觸發了item與element的事件,此時使用stopPropagation沒法阻止這種事件。

stopImmediatePropagation登場~
他能夠阻止事件冒泡而且阻止相同事件的其餘偵聽器被調用

$('.element').on('click', function(e) {
    e.preventDefault(); // 此時連接不會跳轉
    e.stopImmediatePropagation(); // item的點擊事件將被阻止
    console.log('element 被點擊了');
});

$('.item').on('click', function(e) {
    console.log('item 被點擊了');
});

這裏咱們要注意的一點是:stopImmediatePropagation的代碼要儘可能放到其餘同級競爭事件代碼的上面,如上面的例子中,爲了使stopImmediatePropagation起做用,咱們將element的事件監聽代碼放到了item以前!

運行最後一例中的代碼,將只會看到:

"element 被點擊了"
相關文章
相關標籤/搜索