DOM的事件委托(Event delegation)是通過事件 ”冒泡“ (event propagation) 來用單個父節(jié)點而非多個子節(jié)點響應(yīng) UI Events 的技巧汛闸。
冒泡
什么是冒泡?事件被綁定到它的目標節(jié)點 EventTarget
上拱烁,當事件監(jiān)聽器發(fā)現(xiàn)事件被觸發(fā)后,將順著目標節(jié)點的父級鏈逐層檢查粱坤,并觸發(fā)額外的事件監(jiān)聽器立轧,這種動作持續(xù)向父級傳遞,包括 Document
宅广。
有了事件冒泡瀑构,事件委托就有了基礎(chǔ)裆针,可以將事件的處理程序綁定給一個父級元素,當任何子節(jié)點觸發(fā)了匹配的父級元素綁定的事件,即可觸發(fā)父級節(jié)點的處理程序世吨,這就是 事件委托 澡刹。
栗子:
<ul onclick="alert(event.type)">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
上面示例中,即時沒有給每個 <li>
綁定事件耘婚,也會在點擊任何一個 <li>
節(jié)點后彈出 "click" 像屋。
優(yōu)點
- 減少事件綁定,事件委托將很多子元素的事件綁定都集中到一個通用的父元素边篮,使得動態(tài)創(chuàng)建和移除的元素更加方便己莺,不需要考慮元素的事件綁定邏輯。假設(shè)需要對
<li>
標簽進行增加戈轿,只管進行操作就行凌受,不用增加元素的 “onclick” 事件。 - 減少事件監(jiān)聽使用的內(nèi)存思杯,這可能對那些經(jīng)常重新加載的小頁面效果不明顯胜蛉,但是對需要長時間運行的應(yīng)用很重要。因為當元素被從 DOM 中移除之后很難追蹤它對內(nèi)存的使用色乾,造成內(nèi)存泄露誊册,這是由元素的事件綁定造成的。有了事件委托暖璧,在移除子元素之后不用擔心沒有解除綁定事件案怯。
使用
JavaScript
假設(shè)有一個父級元素 ul
和若干子元素 li
:
<ul id="parent">
<li id="child-1">Child 1</li>
<li id="child-2">Child 2</li>
<li id="child-3">Child 3</li>
<li id="child-4">Child 4</li>
<li id="child-5">Child 5</li>
<li id="child-6">Child 6</li>
</ul>
現(xiàn)在希望每一個 li
被點擊時可以獲取到它的內(nèi)容,當事件冒泡到 ul
時澎办,檢查事件的 target
屬性來獲得被點擊的節(jié)點嘲碱,從而獲取內(nèi)容:
// 獲取元素并且添加監(jiān)聽事件
document.getElementById("parent").addEventListener("click", function(e) {
// e.target 是被點擊的元素
if(e.target && e.target.nodeName == "LI") {
// List item found! Output the ID!
alert(e.target.innerHTML+ " was clicked!");
}
});
jQuery.delegate
<ul id="jQueryDelegate">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
$("#jQueryDelegate").delegate("li", "click", function () {
$("#jQueryDelegate").append("<li>jQuery.delegate new item</li>");
});
jQuery.on
<ul id="jQueryOn">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
$("#jQueryOn").on("click", "li", function () {
$("#jQueryOn").append("<li>jQuery.on new item</li>");
});