文章出處

因為有父, 子節點同在, 因為有監聽事件和瀏覽器默認動作之分. 使用 JavaScript 時為了達到預期效果經常需要阻止事件和動作執行. 一般我們會用到三種方法, 分別是 stopPropagation()preventDefault() 和 return false. 它們之間有什么區別, 該何時使用呢? 將在本文中進行講解.

術語

監聽事件, 在在節點上能被監聽的頁面操作. 如: select 節點的 change 事件, a 節點的 click 事件.
瀏覽器默認動作, 指特定頁面元素上帶有的功能. 如: 點擊 a 鏈接節點的跳轉動作, 表單提交動作.

stopPropagation()

因為事件可以在各層級的節點中傳遞, 不管是冒泡還是捕獲, 有時我們希望事件在特定節點執行完之后不再傳遞, 可以使用事件對象的stopPropagation() 方法.

假設頁面上存在一個浮動彈出層, 顯示在最前面, 當點擊彈出層以外頁面區域時, 隱藏彈出層. 為了做到這樣的效果, 我們會監聽documentElement 的 click 事件, 一旦事件被觸發即隱藏彈出層. 但是...

這顯然存在問題. 當用戶點擊彈出層時, 我們不希望它隱藏掉. 但因為事件的冒泡傳遞, documentElement 的 click 事件也會被觸發. 這個時候, 我們可以監聽彈出層的 click 事件, 并使用 stopPropagation() 方法阻止冒泡. 請參考下面的代碼.

// 在彈出對話框上點擊時, 不進行任何頁面操作, 并阻止冒泡
document.getElementById('dialog').onclick = function(ev) {
        ev.stopPropagation();};
 
// 在 documentElement 節點上監聽到點擊事件時, 隱藏對話框
document.documentElement.onclick = function(ev) {
        document.getElementById('dialog').style.display = 'none';};

stopPropagation() 相當好用, 可是 IE8 及以前版本都不支持. IE 的事件對象包含特有的屬性 cancelBubble, 只要將它賦值為 false 即可阻止事件繼續. 如:

// 在彈出對話框上點擊時, 不進行任何頁面操作, 并阻止冒泡
document.getElementById('dialog').onclick = function(ev) {
        ev.cancelBubble = false;};

preventDefault()

一個帶事件監聽的鏈接代碼如下:

<a href="http://w3c.org" onclick="alert('JavaScript Click Event');">點擊鏈接</a>

點擊該鏈接, 顯示對話框后跳轉頁面. 由此可知, 除了執行監聽事件還會觸發瀏覽器默認動作; 執行監聽事件在前, 觸發瀏覽器默認動作在后.

這里有個經典示例, 我們希望點擊鏈接在新窗口打開頁面, 但不希望當前頁面跳轉. 這個時候可以使用 preventDefault() 阻止后面將要執行的瀏覽器默認動作.

<a id="link" href="http://w3c.org">W3C 首頁鏈接</a>
 
<script>
// 在新窗口, 打開頁面
document.getElementById('link').onclick = function(ev) {
        // 阻止瀏覽器默認動作 (頁面跳轉)
        ev.preventDefault();
        // 在新窗口打開頁面
        window.open(this.href);
};
</script>

return false

退出執行, return false 之后的所有觸發事件和動作都不會被執行. 有時候 return false 可以用來替代stopPropagation() 和 preventDefault(), 比如我們上面新窗口打開鏈接的例子, 如:

<a id="link" href="http://w3c.org">W3C 首頁鏈接</a>
 
<script>
// 在新窗口, 打開頁面
document.getElementById('link').onclick = function(ev) {
        // 在新窗口打開頁面
        window.open(this.href);
        // 退出執行 (在監聽事件之后執行的瀏覽器默認動作將不會被執行)
        return false;
};
</script>

有人認為 return false = stopPropagation() + preventDefault(), 其實是錯的. return false 不但阻止事件, 還可以返回對象, 跳出循環等... 方便地一刀切而不夠靈活, 濫用易出錯.


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()