事件委託詳解最新版

1、事件傳播機制

想要深刻了解委託,最好先深刻理解事件傳播機制:javascript

咱們把事件分爲三個階段:捕獲階段目標階段冒泡階段;html

  1. 捕獲階段:當點擊時,先通過捕獲階段,從最外層如html(這裏不考慮兼容了)層層找到目標
  2. 目標階段:通過目標階段,響應事件
  3. 冒泡階段:從點擊目標往外層層觸發相同的事件方法直到最外層(根節點)

觸發當前元素的某一個事件(點擊事件)行爲,不只當前元素事件行爲觸發,並且其祖先元素的相關事件行爲也會依次被觸發,這種機制就是 「事件的冒泡傳播機制」java

如圖:面試

若是有不太理解的能夠看這個小🌰哦😯:ajax

好比某一天你在河邊玩耍,,走着走着,看到一個小石子,哼,把小石子往河裏一扔,河就泛起了層層波浪,對不對啦。這個時候就叫作冒泡瀏覽器

2、事件栗子(冒泡)

栗子

<div id="parent">
	<div id="child">按鈕</div>
</div>
<script> const parent=document.getElementById('parent'); const child=document.getElementById('child'); parent.addEventListener('click',function(){ console.log('parent'); }) child.addEventListener('click',function(){ console.log('child'); }) //通過上面的分析很容易得出結果,小朋友們大家本身算哦 </script>
複製代碼

注意dom0和dom2事件機制不一樣;

dom0:在屬性上掛載,同一個元素只能有一個點擊事件,多個點擊事件,後者會覆蓋前者;app

dom2:在EventTarget.prototype定義的,同一個元素多個點擊事件不會覆蓋,都會執行;原理是有一個統一的事件池;觸發時,瀏覽器會把事件池中全部的按照存放順序發放dom

這裏就很少說啦啦啦啦,有一點偏離主題異步

3、委託的優勢(經典例子)

1. 減小內存的消耗

由於綁定事件越多,瀏覽器內存佔用越大,嚴重影響性能 仍是舉個🌰吧:性能

  • 有100條數據,100個li,給每一個li都加事件,佔用內存很大,因此,利用冒泡機制,在父元素上添加點擊事件:以下
<ul id="ul">
</ul>
<script> const ul=document.getElementById('ul'); for(let i=0;i<100;i++){ let li=document.createElement('li'); li.innerHTML=i; ul.appendChild(li); } ul.addEventListener('click',function(e){ if(e.target.tagName==='UL') return; e.target.className=e.target.className.indexOf('color')===-1?'color':''; })//可自行執行;color是類名能夠在style中添加本身喜歡的顏色,666 </script>
複製代碼

2. ajax的出現,局部刷新的盛行,致使每次加載完,都要從新綁定事件(這裏就使用setTimeout異步代替了)

<ul id="ul">
	<li>666</li>
</ul>
<script> const ul=document.getElementById('ul'); const lists=ul.getElementsByTagName('li'); setTimeout(()=>{ for(let i=0;i<100;i++){ let li=document.createElement('li'); li.innerHTML=i; ul.appendChild(li); } },400) for(let i=0;i<lists.length;i++){ lists[i].onclick=function(){ alert(i); } } //結果只點擊666彈窗;怎麼解決;你們動動腦子吧;相信大家是最棒的 </script>
複製代碼

4、委託的侷限性

  1. 好比 focus、blur 之類的事件自己沒有事件冒泡機制,因此沒法委託;
  2. mousemove、mouseout這樣的事件,雖然有事件冒泡,可是隻能不斷經過位置去計算定位,對性能消耗高,所以也是不適合於事件委託的;

5、使用委託的注意項(能夠叫應用項)

  1. 只在必須的地方,使用事件委託,好比:ajax的局部刷新區域
  2. 儘可能的減小綁定的層級,而且不在body元素上,進行綁定;(事件委託的原理離不開DOM的查找;而瀏覽器太多層級的查找很是耗性能
  3. 減小綁定的次數,若是能夠,那麼把多個事件的綁定,合併到一次事件委託中去,由這個事件委託的回調,來進行分發。

6、經典面試題

mouseeneter 和 mouseover 的區別?

inner.onmouseenter = function () {
    console.log('inner enter');
};
outer.onmouseenter = function () {
    console.log('outer enter');
};
inner.onmouseleave = function () {
    console.log('inner leave');
};
outer.onmouseleave = function () {
    console.log('outer leave');
};
複製代碼

講解:

  1. over屬於滑過(覆蓋)事件,從父元素進入到子元素,屬於離開了父元素,會觸發父元素的out,觸發子元素的over;enter屬於進入,從父元素進入子元素,並不算離開父元素,不會觸發父元素的leave,觸發子元素的enter
  2. enter和leave阻止了事件的冒泡傳播,而over和out還存在冒泡傳播的

因此對於父元素嵌套子元素這種狀況,使用OVER會發生不少不肯意操做的事情,此時咱們使用ENTER會更加簡單,操做方便,因此真實項目中ENTER的使用會比OVER多

此文章中未涉及到兼容性,有時間再加8⃣️

相關文章
相關標籤/搜索