Contents

[JS]event.preventDefault和event.stopPropagation

在開發網頁功能時,事件處理是很常見的需求。event.preventDefault()event.stopPropagation() 是兩個長得很像、但作用完全不同的方法,初學者很容易搞混,這篇筆記整理兩者的差異與使用情境。

event.preventDefault():阻止預設行為

瀏覽器對某些 HTML 元素有預設行為,例如:

  • <a> 點擊後跳頁
  • <form> 提交後重新載入
  • 勾選 <input type="checkbox"> 會改變勾選狀態

preventDefault() 可以阻止這些預設行為,但事件仍會繼續傳遞(冒泡)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 阻止超連結跳頁
$(document).ready(function () {
    $('a[disabled]').click(function (event) {
        event.preventDefault(); // 不跳頁,但 click 事件仍繼續傳遞
    });
});

// 阻止表單送出
$('form').submit(function (event) {
    event.preventDefault();
    // 自行處理資料驗證
});

event.stopPropagation():阻止事件冒泡

DOM 事件預設以**冒泡(Bubbling)**方式傳遞,從觸發元素向上傳遞到父元素、祖先元素,直到 document

stopPropagation() 阻止事件繼續向上傳遞,但不阻止預設行為

1
2
3
4
5
6
7
8
9
// 點擊按鈕不觸發父元素的 click 事件
$('#child-button').click(function (event) {
    event.stopPropagation(); // 不冒泡,父元素的 click 不觸發
    console.log('子元素被點擊');
});

$('#parent-div').click(function () {
    console.log('這不會被執行(如果點擊的是子按鈕)');
});

兩者的比較

方法 阻止預設行為 阻止事件冒泡
preventDefault()
stopPropagation()
return false(jQuery)

jQuery 中的 return false

在 jQuery 事件處理函式中,return false 等同於同時呼叫 preventDefault()stopPropagation()

1
2
3
$('a').click(function () {
    return false; // 等於 event.preventDefault() + event.stopPropagation()
});

注意:原生 JavaScript 的事件處理中,return false 只阻止預設行為(等同 preventDefault()),不阻止冒泡,行為和 jQuery 不同。

事件捕獲(Capturing)

題外話,jQuery 預設使用**冒泡(Bubbling)**階段,沒有提供事件捕獲的設定。若要使用捕獲,需要用原生的 addEventListener

1
2
// 第三個參數 true = 捕獲階段觸發,false(預設)= 冒泡階段觸發
document.getElementById('parent').addEventListener('click', handler, true);

CSS 的另一種做法:pointer-events: none

如果只是要讓元素無法點擊,可以用 CSS 屬性,不需要 JavaScript:

1
2
3
4
5
.disabled {
    pointer-events: none;  /* 無法接受任何滑鼠事件 */
    opacity: 0.5;          /* 視覺上顯示為停用狀態 */
    cursor: not-allowed;   /* 顯示禁止游標 */
}
1
<a href="/somewhere" class="disabled">停用的連結</a>

這個做法簡潔,但要注意鍵盤導航(Tab + Enter)仍可觸發連結,若有無障礙需求,還是需要搭配 JavaScript 處理。