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

一、由來

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

二、概念

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

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

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

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

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

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

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

三、圖解

image.png

四、執(zhí)行順序

現(xiàn)代瀏覽器都采用先捕獲后冒泡的順序,而在目標(biāo)階段,如果對同樣的觸發(fā)源,有多個響應(yīng)事件的話,按事件添加的先后順序執(zhí)行。

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

結(jié)果:

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

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

五、事件委托

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

<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的響應(yīng)操作給ul是可以考慮的,這就是事件委托。

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容