? ??? 今天呢,咱們來說說事件委托,有的相關資料叫事件代理.
? ??? 首先呢,先來講講事件委托的起源:由于事件處理程式可以為web應用提供互動能力,因此很多開發人員會不分青紅皂白的向頁面中添加大量的處理程式.在js中,添加到頁面的事件處理程式數量直接關系到頁面的整體運維性能.導致這一問題的原因是多方面的.首先:
??? 1 函式都是物件,都會占用記憶體,記憶體中物件越多,性能越差
??? 2 事先指定所有的事件處理程式而導致dom訪問次數,會延遲整個頁面的互動的就緒事件.
所以:對事件處理程式過多問題的解決方案就是事件委托.
舉個栗子

<ul id = 'ul1'>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
...
<li>100</li>
</ul>
??? 如果咱們頁面上有100個li標簽,如果要實作點擊li變成紅色,我們雖然可以用for回圈,給每個li添加事件,那這樣就為它們添加了100個事件處理程式,若在一個復雜的web程式中,都使用這種方式,那結果就是數不清的添加事件處理.那么這里是極其浪費資源的.所以這里可以得到一個結論:
? ??? 事件委托,最重要的功能就是提高程式運行效率.
? ??? 既然出來了事件委托,那咱們講講事件委托的原理.先來個概念:事件流.
? 事件流分為
? 1.事件捕獲
? ??? 當一個事件觸發后,從Window物件觸發,不斷經過下級節點,直到目標節點,在事件到達目標節點之前的程序就是捕獲階段,所有經過的節點,都會觸發對應的事件
? 2.事件冒泡
? ??? 當事件到達目標節點后,會沿著捕獲階段的路線原路回傳,同樣,所有經過的節點,都會觸發對應的事件

那現在直接上代碼,帶大家來了解什么是事件捕獲和事件冒泡
<div id = 'div1'>
爺爺
<div id = 'div2'>
父親
<div id = 'div3'>
孫子
</div>
</div>
</div>
<style>
div{padding: 50px; color: white; font-size: 20px;}
#div1{background-color: orange;}
#div2{background-color: blue;}
#div3{background-color: red;}
<style>
??? 例如,咱們都給這三個div同時系結了點擊事件,那我在點擊孫子時,按常理來說,是不是也是點擊了父親和爺爺呢,所以呢,咱們點擊了孫子的click事件,那么這個事件就會向dom樹上傳播,也就是這個順序
div3>div2>div1>body>html>document.....
???那么呢,這就是事件冒泡,而事件捕獲正好相反,在事件捕獲程序中,document首先接到click事件,然后沿著document向下,一直傳播到事件的實際目標.也就是按著這個順序
document>html>body>div1>div2>div3
??? 但傳統的事件的系結沒有辦法實作事件捕獲的,咱們的默認事件流還是事件冒泡!
??? 事件冒泡:由里向外逐級向外觸發(必須由父子關系的組件)(默認事件流)
??? 事件捕獲:由外向里逐級向外觸發(必須由父子關系的組件) 傳統的事件的系結沒有辦法實作
??? 好,這里有人問了,既然咱們講的是事件委托,為什么這里要將事件流的事件冒泡和事件捕獲呢.其實咱們要實作的事件委托原理就是事件冒泡!那接著來說咱們上述的案例,現在需求來了,如果要給100個,1000個li標簽同時系結onclick事件,咱們這里用最高效的方式進行系結,沒錯,就是事件委托.
<ul id = 'ul1'>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
...
<li>100</li>
</ul>
??? 要給這100個li標簽系結事件,當我們單擊li時,當前被點擊的li標簽背景顯示紅色.同時呢,這里又產生了一個問題:父級那么多子元素,怎么區分事件本應該是哪個子元素的?答案是咱們的事件中有個event物件,而event物件里記錄的有“事件源”,它就是發生事件的子元素,咱們在寫的時候,這個獲取event的事件源是有IE兼容性的. 在低版本中的獲取是window.event.srcElement;而在咱們其他瀏覽器是可以直接通過event.target獲取的,咱們一般的寫法是
var target = event.target || window.event.srcElement;//短路操作
那咱們通過事件委托來實作
var oUl = document.getElementById("ul1");
//委托ul上的點擊事件,將當前點擊的li節點變成紅色,
oUl.onclick = function(ev){
//獲取事件物件短路操作,兼容IE
var e = ev || window.event;
//獲取事件源 target 這里也要兼容IE
var target = e.target || window.event.srcElement;
//判斷target是否符合要求的元素節點
if(target.tagName.toLowerCase() == "li"){
//將當前點擊這個li節點變成紅色
target.style.backgroundColor = 'red';
}
}
這里咱們就真真實實的實作了一個事件委托,而且,就只系結了一個事件,把這個事件給了ul標簽.咱們通過點擊li,然后通過冒泡原理 子元素身上的事件會冒泡到父元素身上 那這里是不是比傳統的實作方式方便了很多呢,而且節省了大量的記憶體資源.沒有那么多事件處理程式了,這是對web程式的一個性能的優化.綜上,可以總結出要實作事件委托,必須遵從的三個條件:
??? 1、找要添加行為的節點的父節點或者祖先節點
??? 2、將事件系結在找到的父節點上
??? 3、找到觸發物件,判斷是否符合要求,如果符合要求,進行后續操作,
??? 其實事件委托的好處不僅止于此,再來個需求,在頁面上給一個按鈕,通過點擊按鈕,然后給ul標簽新加一個ul標簽.那這個新加的li標簽,也要實作上面兄弟級一樣的功能.傳統事件中,咱們需要為新加的系結事件,那不是非常的麻煩嗎.
//為了給新加標簽內容標識
var i = 6;
var oBtn = document.getElementById("btn1");
oBtn.onclick = function(){
//創建一個新的li標簽
var newLi = document.createElement("li");
//給新加的標簽添加內容
newLi.innerHTML = 111 * i++;
//將新加的li標簽,添加到ul元素的末尾
oUl.appendChild(newLi);
}
??? 我們這里通過事件委托來實作,上述新加的li標簽,同樣也享受li兄弟級的一樣的功能.那就是后添加節點,擁有前面系結好的函式,
??? 事件委托的優點:
??? 1.提高性能:每一個函式都會占用記憶體空間,只需添加一個事件處理程式代理所有事件,所占用的記憶體空間更少,
??? 2.動態監聽:使用事件委托可以自動系結動態添加的元素,即新增的節點不需要主動添加也可以一樣具有和其他元素一樣的事件,
??? 那今天的js事件委托就講到這里了,歡迎各位大佬來噴,評論區留給你們
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/146964.html
標籤:JavaScript
上一篇:基于 React 實作一個 Transition 過渡影片組件
下一篇:js運動
