1. <span id="abflz"><sup id="abflz"></sup></span>
    2. 為了賬號安全,請及時綁定郵箱和手機立即綁定

      事件捕獲與事件冒泡

      2019.08.07 12:28 286瀏覽

      綁定事件的接口

      為節點綁定事件的方式大致可以分為以下三種:

      例子:

      直接將事件寫在 HTML 文檔中

      <button onclick='showMessage()'>OK</button>
      
      function showMessage() {
          console.log('hello');
      };
      //輸出:hello
      

      以節點屬性的方式綁定事件

      <button id='btn'>OK</button>
      
      var btn = document.getElementById('btn')
      btn.onclick = function() {
          console.log(this.id);
      };
      //輸出:btn
      

      使用 DOM 標準中事件綁定的方法

      <button id='btn'>OK</button>
      
      var btn = document.getElementById('btn')
      btn.addEventListener('click', function() {
          console.log(this.id);
      });
      //輸出:btn
      

      這一部分的詳細介紹,可以參考以下手記:
      JavaScript事件處理程序

      事件捕獲與事件冒泡

      每個事件都有屬性來標記該事件的目標節點,當事件到達目標節點的時候,事件處理程序就會被調用。那么,事件流在 DOM 節點中是如何流動,直至找到目標節點的呢?針對這個問題,早期的渲染引擎有著不同的解析方式,也因此誕生了事件捕獲和事件冒泡兩種完全相反的事件流機制。

      事件捕獲

      事件捕獲強調,事件流由最外層開始,直到目標節點。

      例子:

      //代碼中省略了 html、head 和 body 元素
      <div>
      <p>hello</p>
      </div>
      
      var document = document,
          html = document.documentElement,
          body = document.body,
          div = body.firstElementChild,
          p = div.firstElementChild;
      
      document.addEventListener("click", () => {
          console.log("#document")
      }, true);
      html.addEventListener("click", () => {
          console.log("HTML")
      }, true);
      body.addEventListener("click", () => {
          console.log("body")
      }, true);
      div.addEventListener("click", () => {
          console.log("div")
      }, true);
      p.addEventListener("click", () => {
          console.log("p")
      }, true);
      

      例子中,事件流到達的順序為:
      #document -> HTML -> body -> div -> p

      如果從 DOM 樹上去觀察事件流,順序是由上而下:

      圖片描述

      之所以早期的渲染引擎,例如網景瀏覽器,選擇支持事件捕獲機制,主要是從計算機的工作順序來看待事件流的。實際上,當我們使用鼠標點擊頁面上的按鈕時,并不會真正地" 觸碰 "到按鈕,我們只是簡單地按了一下鼠標的鍵,是操作系統計算出鼠標的位置信息,反饋給瀏覽器,然后瀏覽器根據坐標信息,逐步找到目標節點。這個過程,就是由外而內進行的。

      事件冒泡

      與事件捕獲完全相反,事件冒泡強調,事件流由最內層開始,直到根節點。

      例子:

      //代碼中省略了 html、head 和 body 元素
      <div>
          <p>hello</p>
      </div>
      
      var document = document,
          html = document.documentElement,
          body = document.body,
          div = body.firstElementChild,
          p = div.firstElementChild;
      
      document.addEventListener("click", () => {
          console.log("#document")
      });
      html.addEventListener("click", () => {
          console.log("HTML")
      });
      body.addEventListener("click", () => {
          console.log("body")
      });
      div.addEventListener("click", () => {
          console.log("div")
      });
      p.addEventListener("click", () => {
          console.log("p")
      });
      

      例子中,事件流到達的順序為:
      p -> div -> body -> HTML -> #document

      如果從 DOM 樹上去觀察事件流,順序是由下而上:

      圖片描述

      事件冒泡最早由微軟公司提出,并應用到 IE 瀏覽器中。這一事件機制是比較符合人類邏輯思維的,因為當你按下電腦的關機鍵時,你也同時按在了電腦上。

      統一標準

      最后,規范制定者采取了一種折中的方式,統一了標準,即先捕獲,再冒泡。并在 DOM 底層接口上,加入了 EventTarget (1)類型,用以控制事件是捕獲還是冒泡。實際上,大部分開發者不需要關心事件捕獲,我們只需要使用接口中默認的冒泡模式即可。

      (1) 我們可以通過谷歌瀏覽器看一下 DOM 事件的接口。在谷歌瀏覽器中打印 Node.__proto__,可以發現 Node 節點的原型是 EventTarget;接下來打印 EventTarget.prototype,可以看到 DOM 綁定事件的方法 addEventListener 等都是寫在 EventTarget 中。

      圖片描述

      事件委托

      具體內容,可以參考下面的手記:
      JavaScrip事件委托


      如有錯誤,歡迎指正,本人不勝感激。

      點擊查看更多內容

      本文首次發布于慕課網 ,轉載請注明出處,謝謝合作

      1人點贊

      若覺得本文不錯,就分享一下吧!

      評論

      相關文章推薦

      正在加載中
      意見反饋 邀請有獎 幫助中心 APP下載
      官方微信

      舉報

      0/150
      提交
      取消
      成人在线av