什么是事件代理?首先得知道什么是事件,並且弄清楚事件流,才能真正明白事件代理原理。
一、什么是事件?
javascript與HTML之間交互就是通過事件實現的,事件就是文檔或瀏覽器窗口中發生的一些特定的交互瞬間。如onload、onclick、onmouseup、onmousedown... 。
二、事件流
DOM(文檔對象模型)結構是一個樹型結構,當一個HTML元素產生一個事件時,該事件會在元素結點與根結點之間的路徑傳播,路徑所經過的結點都會收到該事件,這個傳播過程可稱為DOM事件流。
因為歷史的原因,IE最開始實現實現事件流的方式:冒泡事件(event bubbling),Netscape提出了另外一種事件流方式:事件捕獲(event capturing),不同的瀏覽器實現上有一些差別,用起來就有些繁瑣。幸好現代瀏覽器都實現了W3C制定的"DOM2級事件","DOM2級事件"把事件流分為三個階段,捕獲階段、目標階段、冒泡階段。
網上借圖:
三、什么是事件代理?
前面做了這么多基礎鋪墊,那么現在理解事件代理就是很簡單的事了。事件代理就是在祖先級DOM元素綁定一個事件,當觸發子孫級DOM元素的事件時,利用事件流的原理來觸發綁定在祖先級DOM的事件。聽起來有點繞口,下面做一個簡單的代碼實現:
<!--省略html主體部分--> <ul id="menu"> <li><p><a>如果我被釵神翻牌,我就有一個成為大神的機會!</a></p></li> <li><p><a>如果我被釵神翻牌,我就有一個成為大神的機會!</a></p></li> <li><p><a>如果我被釵神翻牌,我就有一個成為大神的機會!</a></p></li> <!--中間省略1000000行--> <li><p><a>如果我被釵神翻牌,我就有一個成為大神的機會!</a></p></li> </ul>
// 獲取祖先節點(這兒就獲取ul),並為它添加一個click事件 document.getElementById("menu").addEventListener("click", function(e) { // 檢查事件源e.targe是否為A if(e.target && e.target.nodeName.toUpperCase == "A") { console.log("釵神翻我牌,今晚就跟你走...."); } });
瀏覽器的能力還是有限的,為了安全起見,系統分配給瀏覽器的內存也是有限的。特別是某些老版本的瀏覽器,如果在DOM上添加的事件過多,會導致網頁的性能下降甚至崩潰。看我上面的ul下面的a節點就有1000004,如果真的為所有的a標簽加一個事件,這個代價是很大的。用了事件代理,我們節約了1000003個事件,簡直太強大了。
一般瀏覽器觸發事件都是在冒泡階段,如果你想在捕獲階段觸發事件你可以設置addEventListener第三個參數為true,addEventListener("click", function(e){}, true)。
總結:基礎很重要,明白基礎,原理就是那么簡單!