在 JavaScript 中,事件委託(delegate)也稱為事件託管或事件代理,就是把目標節點的事件係結到祖先節點上。這種簡單而優雅的事件註冊方式是基於事件傳播過程中,逐層冒泡總能被祖先節點捕獲。
這樣做的好處:優化程式碼,提升執行效能,真正把 HTML 和 JavaScript 分離,也能防止出現在動態新增或刪除節點過程中註冊的事件丟失的現象。
範例1
下面範例使用一般方法為列表結構中每個列表專案系結 click 事件,單擊列表專案,將彈出提示對話方塊,提示當前節點包含的文字資訊。但是,當我們為列表框動態新增列表專案之後,新新增的列表專案沒有繫結 click 事件,這與我們的願望相反。
<button id="btn">新增列表專案</button>
<ul id="list">
<li>列表專案1</li>
<li>列表專案2</li>
<li>列表專案3</li>
</ul>
<script>
var ul = document.getElementById("list");
var lis = ul.getElementsByTagName("li");
for (var i = 0; i < lis.length; i ++) {
lis[i].addEventListener('cluick', function (e) {
var e = e || window.event;
var target = e.target || e.srcElement;
alert(e.target.innerHTML);
}, false);
}
var i = 4;
var btn = document.getElementById("btn");
btn.addEventListener("click", function() {
var li = document.createElement("li");
li.innerHTML = "專案列表" + i++;
ul.appendChild(li);
});
</script>
範例2
下面範例借助事件委託技巧,利用事件傳播機制,在列表框 ul 元素上繫結 click 事件,當事件傳播到父節點 ul 上時,捕獲 click 事件,然後在事件處理常式中檢測當前事件響應節點型別,如果是 li 元素,則進一步執行下面程式碼,否則跳出事件處理常式,結束響應。
<button id="btn">新增專案列表</button>
<ul id="list">
<li>列表專案1</li>
<li>列表專案2</li>
<li>列表專案3</li>
</ul>
<script>
var ul = document.getElementById("list");
ul.addEventListener('click', function(e) {
var e = e || window.event;
var target = e.target || e.srcElement;
if (e.target && e.target.nodeName.toUpperCase()=="LI") {
alert(e.target.innerHTML);
}
}, false);
var i = 4;
var btn = document.getElementById("btn");
btn.addEventListener("click", function () {
var li = document.createElement("li");
li.innerHTML = "專案列表" + i++;
ul.appendChild(li);
});
</script>
當頁面存在大量元素並且每個元素註冊了一個或多個事件時,可能會影響效能。存取和修改更過的 DOM 節點時,程式就會更慢;特別是事件連線過程都發生在 load(或 DOMContentReady)事件中時,對任何一個富互動網頁來說,這都是一個繁忙的時間段。另外,瀏覽器需要儲存每個事件控制代碼的記錄,也會佔用更多記憶體。