事件捕獲、冒泡和事件委托

一、由來

為什么要有事件捕獲和事件冒泡?
在主觀意義上,我點擊哪個元素,就只有哪個元素執行事件,這是合理的。
但是呢,在DOM樹中,元素和元素的容器是一體的,就像人的四肢和人是一起的一樣。所以觸發了元素的事件,容器也勢必是觸發了事件的,就像你觸摸了某個人的手臂,勢必表示觸摸了這個人一樣。
為了表示這種“一體”的關系,于是有了事件捕獲和事件冒泡。

二、概念

那么什么是捕獲、什么是冒泡?
為了實現一體關系,有兩種觸發事件的順序。一種是由上至下,一種是由下至上,它們分別是捕獲和冒泡。
為了更好地理解,下面使用現實例子做類比。
冒泡的例子:

人的手臂被針刺到,會感覺到疼痛。

在這個例子中,針直接作用到人的手臂,手臂對被刺這個事件進行響應,發送神經信號。然后,大腦接收這個信號,產生痛覺。這樣從低級神經到高級神經的傳遞順序叫冒泡。也就是:

底層元素先對相應事件做出響應,然后再到上層元素做出響應,依次傳遞,這樣的事件流叫冒泡。

然而,對于捕獲,并不符合這種“一體”關系,反而像是為了實現這種一體關系而建立的機制。這里使用的是層層詢問的方式。

一個按鈕被點擊了,根元素就知道了有元素被點擊了,但是不知道直接被點擊的是誰,但是自己肯定被點擊。先觸發自己的點擊事件,詢問下層元素,下層元素也先觸發點擊事件,再將詢問向下傳遞,直到目標元素。

其中,不管捕獲還是冒泡,(直接被作用元素)目標元素響應事件的過程叫目標過程。

三、圖解

image.png

四、執行順序

現代瀏覽器都采用先捕獲后冒泡的順序,而在目標階段,如果對同樣的觸發源,有多個響應事件的話,按事件添加的先后順序執行。

<div id="parent">
  parent
  <div id="child">child</div>
</div>
var parent = document.getElementById('parent');
var child = document.getElementById('child');
// parent的捕獲響應
parent.addEventListener('click', function(){
  console.log('parent: catch click');
}, true);
// parent的冒泡響應
parent.addEventListener('click', function(){
  console.log('parent: bubble click');
}, false);
// child的捕獲響應
child.addEventListener('click', function(){
  console.log('child: catch click');
}, true);
// child的冒泡響應
child.addEventListener('click', function(){
  console.log('child: bubble click');
}, false);
// child的on綁定
child.onclick = function(){
  console.log('child: on click');
};

結果:

parent: catch click
child: catch click
child: bubble click
child: on click
parent: bubble click

然后,經過將child的on綁定、捕獲、冒泡響應事件調換順序,都可以發現在目標過程并不符合先捕獲后冒泡的約束,而是誰先綁定,誰先觸發。當然,這也是因為它是一個單獨的過程,獨立于捕獲和冒泡過程的原因,因為壓根沒關系嘛。

五、事件委托

其實事件委托就是,不在目標階段對目標事件進行相應,改為放到捕獲和冒泡階段。而由于捕獲和冒泡階段發生在目標元素的上層元素(目標階段的捕獲和冒泡響應事件個人認為不應該劃分到捕獲和冒泡階段比較好),就相當于把事件響應交給了上層元素,這就是事件委托,就這么簡單。

<ul id="ul">
  <li>a</li>
  <li>b</li>
</ul>
var ul = document.getElementById('ul');
ul.addEventListner('click', function(){
   console.log('li被點擊');
}, false);

像上面這個例子,ul是被li撐開的,所以,點擊ul勢必會點擊到li。這樣,把li的響應操作給ul是可以考慮的,這就是事件委托。

提示:由于將多個li元素監聽事件改為只有一個ul元素監聽事件,一定程度上提高了性能。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • ??JavaScript 與 HTML 之間的交互是通過事件實現的。 ??事件,就是文檔或瀏覽器窗口中發生的一些特...
    霜天曉閱讀 3,526評論 1 11
  • 0.起因 前幾天寫業務的時候,碰到了這樣的需求: checkbox在父DIV的里面,但是checkbox綁定了v-...
    CoderMageFox閱讀 931評論 1 0
  • (續jQuery基礎(1)) 第5章 DOM節點的復制與替換 (1)DOM拷貝clone() 克隆節點是DOM的常...
    凜0_0閱讀 1,360評論 0 8
  • 在javascript里,事件委托是很重要的一個東西,事件委托依靠的就是事件冒泡和捕獲的機制,我先來解釋一下事件冒...
    晏子楚閱讀 25,745評論 7 44
  • js之事件機制 1、事件初探 1.1 js事件的概述 JavaScript事件:JavaScript是基于事件驅動...
    道無虛閱讀 2,396評論 0 2