成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

DOM事件流與事件委托

chaos_G / 398人閱讀

摘要:事件流與事件委托事件,即文檔或瀏覽器中發(fā)生的一些特定交互的瞬間,我們可以利用事件監(jiān)聽來預(yù)定事件,當事件發(fā)生的時候執(zhí)行相應(yīng)的處理程序。本文主要討論事件流的三個階段,及利用事件委托機制進行性能優(yōu)化。

事件流與事件委托

事件,即文檔或瀏覽器中發(fā)生的一些特定交互的瞬間,我們可以利用事件監(jiān)聽來預(yù)定事件,當事件發(fā)生的時候執(zhí)行相應(yīng)的處理程序。當事件發(fā)生在某個DOM節(jié)點上時,事件在DOM結(jié)構(gòu)中進行一級一級的傳遞,這便形成了“流”,事件流便描述了從頁面中接收事件的順序。本文主要討論事件流的三個階段,及利用事件委托機制進行性能優(yōu)化。

DOM事件流

關(guān)于事件流的理解,《JS高程三》中有個形象的比喻:

可以想象畫在一張紙上的一組同心圓,如果你把手指放在圓心上,那么你的手指指向的其實不是一個圓,而是紙上所有的圓。...>換句話說,在單擊按鈕的同時,你也單擊了按鈕的容器元素,甚至也單擊了整個頁面。

————《JavaScript高級程序設(shè)計(第三版)》page 345

DOM2級事件中規(guī)定事件流包含3個階段:

捕獲階段

處于目標階段

冒泡階段

首先發(fā)生的是事件捕獲階段,此時事件還沒有傳遞到目標節(jié)點對象上,所以我們就有機會在這個階段進行事件的截。然后是目標節(jié)點接收到事件,最后是事件冒泡階段,可以在這個階段對事件做出處理和響應(yīng)。
我們先定義一段簡單的html結(jié)構(gòu):



  
    
  
  
      
事件捕獲階段

在事件捕獲階段中,先由不具體的節(jié)點(即上層節(jié)點)接收到事件,然后一級一級往下傳遞,直到最具體的目標節(jié)點接收到事件。
在DOM2級事件規(guī)范中,要求事件從document對象開始傳遞,但是諸如Chrome,F(xiàn)irefox等主流瀏覽器卻是從window開始傳遞的。

addEventListener方法的第三個參數(shù)是一個布爾值(可選),指定事件處理程序是否在捕獲或冒泡階段執(zhí)行。 當為true時,則事件處理程序?qū)⒃诓东@階段執(zhí)行。

誤區(qū):無論addEventListener的第三個參數(shù)是否為true,三個階段都會走一遍,這里的第三個參數(shù),指的是處理程序?qū)诓东@或者冒泡階段執(zhí)行,好比是你想買菜,你可以在上班路上,或者下班路上完成買菜,但無論什么時候買菜,你都要把這兩段路程走完。

document.querySelector("#btn").addEventListener("click", function () {
    console.log("btn was clicked");
},true);

document.querySelector("body").addEventListener("click", function () {
    console.log("body was clicked");
},true);

document.querySelector(".box").addEventListener("click", function () {
    console.log("box was clicked");
},true);

document.addEventListener("click", function () {
    console.log("document was clicked");
},true);

window.addEventListener("click", function () {
    console.log("window was clicked");
},true);

點擊click me按鈕后,控制臺依次打印出執(zhí)行結(jié)果:

window was clicked
document was clicked
body was clicked
box was clikced
btn was clicked

很明顯可以看出,在捕獲階段,事件由window對象開始,一級一級地向下傳遞,直到傳遞到最具體的button對象上。

事件冒泡階段

事件冒泡階段與捕獲階段恰好相反,冒泡階段是從最具體的目標對象開始,一層一層地向上傳遞,直到window對象。
addEventListener方法默認就是從冒泡階段執(zhí)行事件處理程序。

document.querySelector("#btn").addEventListener("click", function () {
    console.log("btn was clicked");
});

document.querySelector("body").addEventListener("click", function () {
    console.log("body was clicked");
});

document.querySelector(".box").addEventListener("click", function () {
    console.log("box was clicked");
});

document.addEventListener("click", function () {
    console.log("document was clicked");
});

window.addEventListener("click", function () {
    console.log("window was clicked");
});

點擊click me按鈕后,控制臺依次打印出執(zhí)行結(jié)果:

btn was clicked
box was clikced
body was clicked
document was clicked
window was clicked

上述過程示意圖:

阻止事件冒泡

我們可以使用event.stopPropagation()方法阻止事件冒泡過程,以防止事件冒泡而帶來不必要的錯誤和困擾。
示例:

document.querySelector("#btn").addEventListener("click", function (event) {
    console.log("btn was clicked");
    event.stopPropagation();
});

document.querySelector("body").addEventListener("click", function () {
    console.log("body was clicked");
});

document.querySelector(".box").addEventListener("click", function () {
    console.log("box was clicked");
});

document.addEventListener("click", function () {
    console.log("document was clicked");
});

window.addEventListener("click", function () {
    console.log("window was clicked");
});

點擊click me按鈕后,控制臺打印出執(zhí)行結(jié)果顯示,事件沒有再向上冒泡傳遞給其他節(jié)點對象:

btn was clicked
事件委托

每個函數(shù)都是對象,都會占用內(nèi)存,所以當我們的頁面中所包含的事件數(shù)量較多時,如果給每個節(jié)點綁定一個事件,加上事件處理程序,就會造成性能很差。還有一個問題是,某個元素節(jié)點是后來通過JavaScript動態(tài)添加進頁面中的,這時候我們?nèi)绻崆皩λM行綁定,但此時該元素并不存在,所以會綁定事件會失敗。解決上述兩個問題的一個常用方案,就是使用事件委托。
舉例來說:

document.querySelector(".box").addEventListener(function (event) {
    switch (event.target.id) {
      case "btn":
        console.log("btn was clicked");
        break;
      case "btn-2":
        console.log("btn-2 was clicked");
        break;
      default:
        console.log("box was clicked");
        break;
    }
});
$(".box").append("");

簡單說,事件委托就是把本來該自己接收的事件委托給自己的上級(父級,祖父級等等)的某個節(jié)點,讓自己的“長輩們”幫忙盯著,一旦有事件觸發(fā),再由“長輩們”告訴自己:“喂,孫子,有人找你~~”。
恩,差不多就是這么個意思,可憐天下父母心。

水平有限,歡迎大家不吝指正。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80503.html

相關(guān)文章

  • 好文推薦:javascript: 事件委托解析

    摘要:前言之前不太明白事件委托??戳诉@個帖子,跟著代碼操作了一遍,終于明白了事件委托。推薦理由一步一步,漸進式分析來說明事件委托。為簽收快遞,有兩種辦法一是三個人在公司門口等快遞二是委托給前臺代為簽收。 前言:之前不太明白事件委托。 看了這個帖子,跟著代碼操作了一遍,終于明白了事件委托。所以轉(zhuǎn)載。 推薦理由:一步一步,漸進式分析來說明事件委托。 什么叫事件委托呢?它還有一個名字叫事件代理 ...

    Wuv1Up 評論0 收藏0
  • js 事件委托 事件代理

    摘要:事件委托事件代理高級程序設(shè)計上解釋事件委托就是利用事件冒泡,只指定一個事件處理程序,就可以管理某一類型的所有事件。事件委托原理事件委托是利用事件的冒泡原理來實現(xiàn)的,事件冒泡就是事件從最深的節(jié)點開始,然后逐級向上傳播事件。 js 事件委托 事件代理 JavaScript高級程序設(shè)計上解釋:事件委托就是利用事件冒泡,只指定一個事件處理程序,就可以管理某一類型的所有事件。 通過例子類比: 有...

    widuu 評論0 收藏0
  • Javascript事件

    摘要:見下圖更直觀在事件流中,事件的目標在捕獲階段不會接受到事件,這意味著在捕獲階段,事件從到后就停止了。下一個階段是目標階段,于是事件在上發(fā)生,并在事件處理中被看成是冒泡階段的一部分,然后,冒泡階段發(fā)生,事件又傳回。 CONTENTS DOM事件流 事件冒泡 阻止冒泡 事件捕獲 事件委托 DOM事件流 1.什么是事件流? 事件流所描述的是從頁面中接受事件的順序 2.DOM事件流的三個階...

    baiy 評論0 收藏0
  • Javascript事件

    摘要:見下圖更直觀在事件流中,事件的目標在捕獲階段不會接受到事件,這意味著在捕獲階段,事件從到后就停止了。下一個階段是目標階段,于是事件在上發(fā)生,并在事件處理中被看成是冒泡階段的一部分,然后,冒泡階段發(fā)生,事件又傳回。 CONTENTS DOM事件流 事件冒泡 阻止冒泡 事件捕獲 事件委托 DOM事件流 1.什么是事件流? 事件流所描述的是從頁面中接受事件的順序 2.DOM事件流的三個階...

    luffyZh 評論0 收藏0
  • Javascript事件

    摘要:見下圖更直觀在事件流中,事件的目標在捕獲階段不會接受到事件,這意味著在捕獲階段,事件從到后就停止了。下一個階段是目標階段,于是事件在上發(fā)生,并在事件處理中被看成是冒泡階段的一部分,然后,冒泡階段發(fā)生,事件又傳回。 CONTENTS DOM事件流 事件冒泡 阻止冒泡 事件捕獲 事件委托 DOM事件流 1.什么是事件流? 事件流所描述的是從頁面中接受事件的順序 2.DOM事件流的三個階...

    pcChao 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<