JavaScript的事件代理和委托實(shí)例分析
在JavaScript中,經(jīng)常會(huì)碰到要監(jiān)聽(tīng)列表中多項(xiàng)li的情形,假設(shè)我們有一個(gè)列表如下:
<ul id="list">
<li id="item1">item1</li>
<li id="item2">item2</li>
<li id="item3">item3</li>
<li id="item4">item4</li>
</ul>
如果我們要實(shí)現(xiàn)以下功能:當(dāng)鼠標(biāo)點(diǎn)擊某一li時(shí),alert輸出該li的內(nèi)容,我們通常的寫(xiě)法是這樣的:
當(dāng)列表項(xiàng)比較少時(shí),直接給每個(gè)li添加onclick事件
列表項(xiàng)比較多時(shí),在onload時(shí)就給每個(gè)列表項(xiàng)調(diào)用監(jiān)聽(tīng)
第一種方法比較簡(jiǎn)單直接,但是沒(méi)有顧及到html與JavaScript的分離,不建議使用,第二種方法的代碼如下:
window.onload=function(){
var ulNode=document.getElementById("list");
var liNodes=ulNode.childNodes||ulNode.children;
for(var i=0;i<liNodes.length;i++){
liNodes[i].addEventListener('click',function(e){
alert(e.target.innerHTML);
},false);
}
}
由上可以看出來(lái),假如不停的刪除或添加li,則function()也要不停的更改操作,易出錯(cuò),因此推薦使用事件代理,在使用事件代理之前,我們先來(lái)了解一下事件階段(event phase):
事件階段:
當(dāng)一個(gè)DOM事件被觸發(fā)的時(shí)候,他并不是只在它的起源對(duì)象上觸發(fā)一次,而是會(huì)經(jīng)歷三個(gè)不同的階段。簡(jiǎn)而言之:事件一開(kāi)始從文檔的根節(jié)點(diǎn)流向目標(biāo)對(duì)象(捕獲階段),然后在目標(biāo)對(duì)向上被觸發(fā)(目標(biāo)階段),之后再回溯到文檔的根節(jié)點(diǎn)(冒泡階段)如圖所示(圖片來(lái)自W3C):
事件捕獲階段(Capture Phase)
事件的第一個(gè)階段是捕獲階段。事件從文檔的根節(jié)點(diǎn)出發(fā),隨著DOM樹(shù)的結(jié)構(gòu)向事件的目標(biāo)節(jié)點(diǎn)流去。途中經(jīng)過(guò)各個(gè)層次的DOM節(jié)點(diǎn),并在各節(jié)點(diǎn)上觸發(fā)捕獲事件,直到到達(dá)時(shí)間的目標(biāo)節(jié)點(diǎn)。捕獲階段的主要任務(wù)是簡(jiǎn)歷傳播路徑,在冒泡階段,時(shí)間會(huì)通過(guò)這個(gè)路徑回溯到文檔根節(jié)點(diǎn)。
element.removeEventListener(<event-name>, <callback>, <use-capture>);
我們通過(guò)上面的這個(gè)函數(shù)來(lái)給節(jié)點(diǎn)設(shè)置監(jiān)聽(tīng),可以通過(guò)將;設(shè)置成true來(lái)為事件的捕獲階段添加監(jiān)聽(tīng)回調(diào)函數(shù)。在實(shí)際應(yīng)用中,我們并沒(méi)有太多使用捕獲階段監(jiān)聽(tīng)的用例,但是通過(guò)在捕獲階段對(duì)事件的處理,我們可以阻止類(lèi)似click事件在某個(gè)特定元素上被觸發(fā)。
var form=document.querySeletor('form');
form.addEventListener('click',function(e){
e.stopPropagation();
},true);
如果你對(duì)這種用法不是很了解的話,最好還是將設(shè)置為false或者undefined,從而在冒泡階段對(duì)事件進(jìn)行監(jiān)聽(tīng)。
目標(biāo)階段(Target Phase)
當(dāng)事件到達(dá)目標(biāo)節(jié)點(diǎn)時(shí),事件就進(jìn)入了目標(biāo)階段。事件在目標(biāo)節(jié)點(diǎn)上被觸發(fā),然后逆向回流,知道傳播到最外層的文檔節(jié)點(diǎn)。
對(duì)于多層嵌套的節(jié)點(diǎn),鼠標(biāo)和指針事件經(jīng)常會(huì)被定位到最里層的元素上。假設(shè),你在一個(gè)div元素上設(shè)置了click的監(jiān)聽(tīng)函數(shù),而用戶點(diǎn)擊在了這個(gè)div元素內(nèi)部的p元素上,那么p元素就是這個(gè)時(shí)間的目標(biāo)元素。事件冒泡讓我們可以在這個(gè)div或者更上層的元素上監(jiān)聽(tīng)click事件,并且時(shí)間傳播過(guò)程中觸發(fā)回調(diào)函數(shù)。
冒泡階段(Bubble Phase)
事件在目標(biāo)事件上觸發(fā)后,并不在這個(gè)元素上終止。它會(huì)隨著DOM樹(shù)一層層向上冒泡,直到到達(dá)最外層的根節(jié)點(diǎn)。也就是說(shuō),同一事件會(huì)一次在目標(biāo)節(jié)點(diǎn)的父節(jié)點(diǎn),父節(jié)點(diǎn)的父節(jié)點(diǎn)...直到最外層的節(jié)點(diǎn)上觸發(fā)。
絕大多數(shù)事件是會(huì)冒泡的,但并非所有的。具體可見(jiàn):規(guī)范說(shuō)明
由上我們可以想到,可以使用事件代理來(lái)實(shí)現(xiàn)對(duì)每一個(gè)li的監(jiān)聽(tīng)。代碼如下:
window.onload=function(){
var ulNode=document.getElementById("list");
ulNode.addEventListener('click',function(e){
if(e.target&&e.target.nodeName.toUpperCase()=="LI"){/*判斷目標(biāo)事件是否為li*/
alert(e.target.innerHTML);
}
},false);
};
以上所述就是本文的全部?jī)?nèi)容了,希望能夠?qū)Υ蠹沂煜avascript事件的委托和代理能夠有所幫助。
請(qǐng)您花一點(diǎn)時(shí)間將文章分享給您的朋友或者留下評(píng)論。我們將會(huì)由衷感謝您的支持!
- JavaScript中的事件處理程序
- JS事件流與事件處理程序?qū)嵗治?/a>
- JavaScript常見(jiàn)事件處理程序?qū)嵗偨Y(jié)
- JavaScript事件處理程序詳解
- 深入理解在JS中通過(guò)四種設(shè)置事件處理程序的方法
- js中的事件委托或是事件代理使用詳解
- JavaScript事件代理和委托詳解
- js事件委托和事件代理案例分享
- JavaScript通過(guò)事件代理高亮顯示表格行的方法
- JS實(shí)現(xiàn)為動(dòng)態(tài)添加的元素增加事件功能示例【基于事件委托】
- javascript事件委托的方式綁定詳解
- JS事件處理機(jī)制及事件代理(事件委托)實(shí)例詳解
相關(guān)文章
小程序自定義導(dǎo)航欄兼容適配所有機(jī)型(附完整案例)
這篇文章主要介紹了小程序自定義導(dǎo)航欄兼容適配所有機(jī)型(附完整案例),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04package.json與package-lock.json的區(qū)別及詳細(xì)解釋
不知道大家平時(shí)在開(kāi)發(fā)中有沒(méi)有注意到,你的項(xiàng)目中有兩個(gè)文件:package.json,package-lock.json,應(yīng)該很多人平時(shí)都不會(huì)去關(guān)注這兩個(gè)文件有啥關(guān)系吧,這篇文章主要給大家介紹了關(guān)于package.json與package-lock.json的區(qū)別及詳細(xì)解釋,需要的朋友可以參考下2022-08-08javascript面向?qū)ο笕筇卣髦鄳B(tài)實(shí)例詳解
這篇文章主要介紹了javascript面向?qū)ο笕筇卣髦鄳B(tài),結(jié)合實(shí)例形式詳細(xì)分析了javascript面向?qū)ο蟪绦蛟O(shè)計(jì)中多態(tài)的概念、原理,并結(jié)合實(shí)例形式總結(jié)了多態(tài)的實(shí)現(xiàn)方法與使用技巧,需要的朋友可以參考下2019-07-07javascript 動(dòng)態(tài)改變onclick事件觸發(fā)函數(shù)代碼
javascript 動(dòng)態(tài)改變onclick事件觸發(fā)函數(shù)代碼,需要的朋友可以參考下。2011-08-08TopList標(biāo)簽和JavaScript結(jié)合兩例
TopList標(biāo)簽和JavaScript結(jié)合兩例...2007-08-08整理關(guān)于Bootstrap導(dǎo)航的慕課筆記
這篇文章主要為大家整理了關(guān)于Bootstrap導(dǎo)航的慕課筆記,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03對(duì)比分析Django的Q查詢(xún)及AngularJS的Datatables分頁(yè)插件
通過(guò)本文給大家對(duì)比分析了Django的Q查詢(xún)及AngularJS的Datatables分頁(yè)插件,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02