委託模式就是利用事件的冒泡機制把一個或者一組元素的事件委託到它的父層或者更外層元素上,準確來講不屬於一般定義的設計模式範疇,但事件委託是一種很是有用的代碼構建技巧。javascript
事件委託,委託模式就是利用事件的冒泡機制把一個或者一組元素的事件委託到它的父層或者更外層元素上,真正綁定事件的是外層元素,當事件響應到須要綁定的元素上時,會經過事件冒泡機制從而觸發它的外層元素的綁定事件上,而後在外層元素上去執行函數。
舉個例子,好比一個宿舍的同窗同時快遞到了,一種方法就是他們都一個個去領取,還有一種方法就是把這件事情委託給宿舍長,讓一我的出去拿好全部快遞,而後再根據收件人一一分發給每一個宿舍同窗。在這裏,取快遞就是一個事件,每一個同窗指的是須要響應事件的DOM
元素,而出去統一領取快遞的宿舍長就是代理的元素,因此真正綁定事件的是這個元素,按照收件人分發快遞的過程就是在事件執行中,須要判斷當前響應的事件應該匹配到被代理元素中的哪個或者哪幾個。css
一般來講,事件主要分爲捕獲與冒泡兩種,IE8
及以前的版本是不支持捕獲事件的,W3C
制定的DOM2
事件模型是標準模型,支持捕獲型事件和冒泡型事件,調用事件的處理階段依次爲捕獲、目標、冒泡。html
Event Capturing
是一種從上而下的傳播方式,以click
事件爲例,其會從最外層根節向內傳播到達點擊的節點,爲從最外層節點逐漸向內傳播直到目標節點的方式。Event Bubbling
是一種從下往上的傳播方式,一樣以click
事件爲例,事件最開始由點擊的節點,而後逐漸向上傳播直至最高層節點。而事件委託一般使用的是冒泡事件模型,對於事件冒泡,當一個元素接收到事件的時候,會把他接收到的事件傳給本身的父級,一直到window
,固然其傳播的是事件,綁定的執行函數並不會傳播,若是父級沒有綁定事件函數,就算傳遞了事件,也不會有什麼表現,但事件確實傳遞了。事件冒泡的緣由是事件源自己可能沒有處理事件的能力,即處理事件的函數並未綁定在該事件源上。它自己並不能處理事件,因此須要將事件傳播出去,從而能達處處理該事件的執行函數。java
舉個例子,當接到一個小需求作一個日曆功能,須要當用戶點擊日曆的格子時,格子的背景色變成灰色,若是咱們爲每個日期元素都綁定一個事件,這樣會增長不少事件監聽,無心中消耗了內存,尤爲是在老版本瀏覽器例如IE6
、IE7
、IE8
等瀏覽器事件過多會影響用戶體驗,而對於這種需求徹底可使用事件委託,將點擊事件冒泡到外層的父元素去處理,在父元素取得冒泡的元素再去調整DOM
結構。另外,使用事件委託還能夠對於將來的更改有必定的預見性,例如咱們有一行文字,點擊彈出文字內容,而若是咱們再在這行文字下加入一行文字,依舊須要爲其添加點擊事件才能作到點擊彈出效果,若是咱們使用事件委託機制,就能夠直接添加文字而不須要再爲其添加事件去處理點擊事件了。此外,在老版本的IE
瀏覽器因爲使用的是引用計數的GC
垃圾回收機制,頗有可能出現因爲沒有對DOM
元素的引用進行顯性的清除而致使的內存泄漏,使用事件委託能夠在必定程度上解決這個問題。下面是一個簡單的事件委託的示例。git
<!DOCTYPE html> <html> <head> <title>事件委託</title> </head> <style type="text/css"> li{ cursor: pointer; } </style> <body> <ul id="u1"> <li uid="0">0</li> <li uid="1">1</li> <li uid="2">2</li> <li uid="3">3</li> <li uid="4">4</li> <li uid="5">5</li> <li uid="6">6</li> <li uid="7">7</li> <li uid="8">8</li> <li uid="9">9</li> </ul> </body> <script type="text/javascript"> document.getElementById("u1").addEventListener("click",(e) => { console.log(e.srcElement.getAttribute("uid")); }) </script> </html>
https://github.com/WindrunnerMax/EveryDay
https://zhuanlan.zhihu.com/p/26536815 https://juejin.cn/post/6844904000639205390 https://www.cnblogs.com/birdshome/archive/2006/06/01/ClosureReferences.html