帶你徹底搞懂JavaScript的事件流
DOM事件流
要明白事件流,首先我們要明白三點(diǎn):
- 元素不是獨(dú)立的,是串聯(lián)在一起的
- 單個(gè)元素觸發(fā)事件以后還會(huì)影響其他元素
- 事件流的方式:事件捕獲(網(wǎng)景提出)、事件冒泡(IE提出)
我們就以上圖為例,假設(shè)你給div綁定了點(diǎn)擊事件,當(dāng)你點(diǎn)擊了div后,其他元素也會(huì)受之牽連,會(huì)引起牽一發(fā)而動(dòng)全身的效果。
事件流的方式有兩種:事件冒泡
、事件捕獲
事件冒泡
事件冒泡階段:在點(diǎn)擊完div后立即觸發(fā)目標(biāo)事件,然后再一層一層向上冒泡
事件捕獲
事件捕獲階段:在點(diǎn)擊完div后不會(huì)立即觸發(fā)div的事件,而是一層一層向下捕獲,最終到達(dá)div才觸發(fā)事件。
其實(shí),這兩種階段,在日后的項(xiàng)目開(kāi)發(fā)中都有可能遇見(jiàn),因?yàn)椴煌慕壎ㄊ录椒?,造就了不同的事件階段(冒泡/捕獲)
情景一:直接在HTML中綁定事件
<body onclick="console.log('我是body')"> <button onclick="console.log('我是button')"> <span onclick="console.log('我是span')">快樂(lè)按鈕</span> </button> </body>
效果:
從上圖可看出,當(dāng)我們點(diǎn)擊span標(biāo)簽以后,上層button身上的事件以及body身上的事件都會(huì)按冒泡順序執(zhí)行
情景二:[domNode].onclick()方式 —— DOM0級(jí)
html:
<body> <button> <span>快樂(lè)按鈕</span> </button> </body>
javascript:
var body = document.getElementsByTagName('body')[0]; var button = document.getElementsByTagName('button')[0]; var span = document.getElementsByTagName('span')[0]; body.onclick = function() {console.log('我是body')}; button.onclick = function() {console.log('我是button')}; span.onclick = function() {console.log('我是span')};
效果:
我們發(fā)現(xiàn),DOM0級(jí)綁定事件的方式依然是冒泡的形式
情景三:[domNode].addEventListener()方式 —— DOM2級(jí)
addEvenListener(事件名,事件觸發(fā)后的回調(diào),布爾值)
false(默認(rèn)):表示在冒泡階段調(diào)用事件處理程序true:表示在捕獲階段調(diào)用事件處理程序
html:
<body> <button> <span>快樂(lè)按鈕</span> </button> </body>
javascript:
var body = document.getElementsByTagName('body')[0]; var button = document.getElementsByTagName('button')[0]; var span = document.getElementsByTagName('span')[0]; function theName() {console.log('我是' + this.nodeName)}; body.addEventListener('click',theName,false); button.addEventListener('click',theName,false); span.addEventListener('click',theName,false);
效果:
我們可以看到當(dāng)addEventListener的第三個(gè)參數(shù)為false(不寫(xiě)默認(rèn)也是false)的時(shí)候,事件流為冒泡。
當(dāng)我們把第三個(gè)參數(shù)改為true時(shí):
...... body.addEventListener('click',theName,true); button.addEventListener('click',theName,true); span.addEventListener('click',theName,true);
我們發(fā)現(xiàn),執(zhí)行順序?yàn)閎ody ——> button ——> span,為事件捕獲階段。
DOM2級(jí)規(guī)定:
- 事件流包括三個(gè)階段(1.捕獲階段 2.目標(biāo)階段 3.冒泡階段)
執(zhí)行循序
應(yīng)遵循:捕獲階段 ——> 目標(biāo)階段 ——> 冒泡階段
也就是說(shuō)當(dāng)你點(diǎn)擊目標(biāo)元素后,不會(huì)立刻執(zhí)行觸發(fā)事件,而是先執(zhí)行事件捕獲階段 ——> 然后處于目標(biāo)階段(觸發(fā)事件) ——> 事件冒泡階段
我們來(lái)看一道經(jīng)典面試題:當(dāng)我們點(diǎn)擊baby嬰兒時(shí)的輸出順序?
html:
<body> <div class="grandma">grandma奶奶 <div class="mother">mother媽媽 <div class="daughter">daughter <div class="baby">baby嬰兒</div> </div> </div> </div> </body>
javascript:
var grandma = document.getElementsByClassName('grandma')[0] var mother = document.getElementsByClassName('mother')[0] var daughter = document.getElementsByClassName('daughter')[0] var baby = document.getElementsByClassName('baby')[0] function theName() { console.log('我是' + this.className); } baby.addEventListener('click', theName, false)//冒泡 daughter.addEventListener('click', theName, true)//捕獲 mother.addEventListener('click', theName, true)//捕獲 grandma.onclick = theName//冒泡
結(jié)果:
做題思路:
- 先給綁定好事件的元素劃分是 捕獲?冒泡?我們可以看到
daughter
和mother
為捕獲
;baby
和grandma
為冒泡
- 因?yàn)镈OM2規(guī)定先捕獲后冒泡,因此會(huì)先打印daughter和mother其中之一
- 因?yàn)椴东@是從上至下(dom根——>div),因此先打印mother后daughter
- 因?yàn)槊芭菔菑南轮辽?div——>dom根),因此打印baby后再打印grandma
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
javascript table美化鼠標(biāo)滑動(dòng)單元格變色
效果非常不錯(cuò)的table美化,當(dāng)鼠標(biāo)滑過(guò)去,背景色變換效果2008-06-06JavaScript Cookie的讀取和寫(xiě)入函數(shù)
Cookie的讀取和寫(xiě)入實(shí)現(xiàn)函數(shù)。2009-12-12微信小程序自定義組件傳值 頁(yè)面和組件相互傳數(shù)據(jù)操作示例
這篇文章主要介紹了微信小程序自定義組件傳值 頁(yè)面和組件相互傳數(shù)據(jù)操作,結(jié)合實(shí)例形式分析了微信小程序常見(jiàn)傳值操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-05-05ES6 Object方法擴(kuò)展的應(yīng)用實(shí)例分析
這篇文章主要介紹了ES6 Object方法擴(kuò)展的應(yīng)用,結(jié)合實(shí)例形式總結(jié)分析了ES6針對(duì)對(duì)象方法的擴(kuò)展與優(yōu)化,需要的朋友可以參考下2019-06-06JavaScript實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)可視化的示例詳解
動(dòng)態(tài)數(shù)據(jù)可視化能夠?qū)⒋罅繑?shù)據(jù)以直觀、生動(dòng)的方式呈現(xiàn),幫助用戶更好地理解和分析數(shù)據(jù),本文主要為大家介紹了如何使用JavaScript實(shí)現(xiàn)這一功能,需要的可以參考下2024-02-02URL的參數(shù)中有加號(hào)傳值變?yōu)榭崭竦膯?wèn)題(URL特殊字符)
今天在調(diào)試客戶端向服務(wù)器傳遞參數(shù)時(shí),參數(shù)中的“+”全部變成了空格,原因是URL中默認(rèn)的將“+”號(hào)轉(zhuǎn)義了,經(jīng)過(guò)以下步驟解決了,需要的朋友可以參考一下2016-11-11JavaScript的removeChild()函數(shù)用法詳解
removechild 函數(shù)可以刪除父元素的指定子元素,通過(guò)本文給大家介紹javascript的removeChild()函數(shù)用法,對(duì)js removechild函數(shù)相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2015-12-12