JavaScript的事件代理和委托實例分析
在JavaScript中,經(jīng)常會碰到要監(jiān)聽列表中多項li的情形,假設(shè)我們有一個列表如下:
<ul id="list">
<li id="item1">item1</li>
<li id="item2">item2</li>
<li id="item3">item3</li>
<li id="item4">item4</li>
</ul>
如果我們要實現(xiàn)以下功能:當(dāng)鼠標點擊某一li時,alert輸出該li的內(nèi)容,我們通常的寫法是這樣的:
當(dāng)列表項比較少時,直接給每個li添加onclick事件
列表項比較多時,在onload時就給每個列表項調(diào)用監(jiān)聽
第一種方法比較簡單直接,但是沒有顧及到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);
}
}
由上可以看出來,假如不停的刪除或添加li,則function()也要不停的更改操作,易出錯,因此推薦使用事件代理,在使用事件代理之前,我們先來了解一下事件階段(event phase):
事件階段:
當(dāng)一個DOM事件被觸發(fā)的時候,他并不是只在它的起源對象上觸發(fā)一次,而是會經(jīng)歷三個不同的階段。簡而言之:事件一開始從文檔的根節(jié)點流向目標對象(捕獲階段),然后在目標對向上被觸發(fā)(目標階段),之后再回溯到文檔的根節(jié)點(冒泡階段)如圖所示(圖片來自W3C):

事件捕獲階段(Capture Phase)
事件的第一個階段是捕獲階段。事件從文檔的根節(jié)點出發(fā),隨著DOM樹的結(jié)構(gòu)向事件的目標節(jié)點流去。途中經(jīng)過各個層次的DOM節(jié)點,并在各節(jié)點上觸發(fā)捕獲事件,直到到達時間的目標節(jié)點。捕獲階段的主要任務(wù)是簡歷傳播路徑,在冒泡階段,時間會通過這個路徑回溯到文檔根節(jié)點。
element.removeEventListener(<event-name>, <callback>, <use-capture>);
我們通過上面的這個函數(shù)來給節(jié)點設(shè)置監(jiān)聽,可以通過將;設(shè)置成true來為事件的捕獲階段添加監(jiān)聽回調(diào)函數(shù)。在實際應(yīng)用中,我們并沒有太多使用捕獲階段監(jiān)聽的用例,但是通過在捕獲階段對事件的處理,我們可以阻止類似click事件在某個特定元素上被觸發(fā)。
var form=document.querySeletor('form');
form.addEventListener('click',function(e){
e.stopPropagation();
},true);
如果你對這種用法不是很了解的話,最好還是將設(shè)置為false或者undefined,從而在冒泡階段對事件進行監(jiān)聽。
目標階段(Target Phase)
當(dāng)事件到達目標節(jié)點時,事件就進入了目標階段。事件在目標節(jié)點上被觸發(fā),然后逆向回流,知道傳播到最外層的文檔節(jié)點。
對于多層嵌套的節(jié)點,鼠標和指針事件經(jīng)常會被定位到最里層的元素上。假設(shè),你在一個div元素上設(shè)置了click的監(jiān)聽函數(shù),而用戶點擊在了這個div元素內(nèi)部的p元素上,那么p元素就是這個時間的目標元素。事件冒泡讓我們可以在這個div或者更上層的元素上監(jiān)聽click事件,并且時間傳播過程中觸發(fā)回調(diào)函數(shù)。
冒泡階段(Bubble Phase)
事件在目標事件上觸發(fā)后,并不在這個元素上終止。它會隨著DOM樹一層層向上冒泡,直到到達最外層的根節(jié)點。也就是說,同一事件會一次在目標節(jié)點的父節(jié)點,父節(jié)點的父節(jié)點...直到最外層的節(jié)點上觸發(fā)。
絕大多數(shù)事件是會冒泡的,但并非所有的。具體可見:規(guī)范說明
由上我們可以想到,可以使用事件代理來實現(xiàn)對每一個li的監(jiān)聽。代碼如下:
window.onload=function(){
var ulNode=document.getElementById("list");
ulNode.addEventListener('click',function(e){
if(e.target&&e.target.nodeName.toUpperCase()=="LI"){/*判斷目標事件是否為li*/
alert(e.target.innerHTML);
}
},false);
};
以上所述就是本文的全部內(nèi)容了,希望能夠?qū)Υ蠹沂煜avascript事件的委托和代理能夠有所幫助。
請您花一點時間將文章分享給您的朋友或者留下評論。我們將會由衷感謝您的支持!
相關(guān)文章
JavaScript數(shù)組去重算法實例小結(jié)
這篇文章主要介紹了JavaScript數(shù)組去重算法,結(jié)合實例形式總結(jié)分析了JavaScript數(shù)組去重相關(guān)的讀寫、遍歷、比較、排序等操作及算法改進相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2018-05-05
基于JS實現(xiàn)Android,iOS一個手勢動畫效果
這篇文章主要介紹了基于JS實現(xiàn)Android,iOS一個手勢動畫效果 的相關(guān)資料,需要的朋友可以參考下2016-04-04
JS JSON對象轉(zhuǎn)為字符串的簡單實現(xiàn)方法
這篇文章主要介紹了JS中JSON對象轉(zhuǎn)為字符串的簡單實現(xiàn)方法。需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11
JavaScript預(yù)解析及相關(guān)技巧分析
這篇文章主要介紹了JavaScript預(yù)解析及相關(guān)技巧,結(jié)合實例形式分析了JavaScript與解析的原理,步驟與相關(guān)技巧,需要的朋友可以參考下2016-04-04

