一、前言
說實話,真問我什么是事件委托,我肯定gg,還好查了一下,原來就是我之前練習過的DOM2級事件的應用。
二、什么是事件委托?
事件委托就是當事件觸發時,把要做的事委托給父元素(或父元素的父元素)來處理。也就是:利用冒泡的原理,把事件加到父級上,通過判斷事件來源的子集,執行相應的操作。使用事件委托技術能讓你避免對特定的每個節點添加事件監聽器。
三、事件委托作用
1.減少事件注冊,節省內存
-table可以代理所有td的click事件
-ul可以代理所有li的click事件
2.能為之后新增的DOM元素自動添加事件(事件委托給了父級,只要是子級,就能代理)
-新增的li不用綁定事件
-刪除li時,不需要解綁
案例演示:
場景1:當多個li標簽需要添加 mouseover 變色時
效果如下圖:
ul{ width: 200px; line-height: 30px; } li.checked{ background-color: aqua; }
<h2>去哪兒開房?</h2> <ul> <li>你家</li> <li>我家</li> <li>如家</li> </ul>
不用事件委托需要遍歷添加事件
window.onload = function(){ let oLi = document.getElementsByTagName('li'); for(let i=0,len=oLi.length;i<len;i++){ // 遍歷所有li oLi[i].onmouseover = function () { this.classList.add('checked') } oLi[i].onmouseout = function () { this.classList.remove('checked') } } }
使用事件委托
window.onload = function(){ let oUl = document.getElementsByTagName('ul')[0]; //事件委托給li的父級 function beenChecked(e) { //e是event事件 e.target.classList.add('checked') //e.target是事件源 } function notChecked(e) { e.target.classList.remove('checked') } oUl.addEventListener('mouseover',beenChecked) // 第三參數默認false,事件冒泡 oUl.addEventListener('mouseout',notChecked) }
場景2:新增的li標簽,自動添加該事件
<button id="btn">新增一條li</button> <h2>去哪兒開房?</h2> <ul> <li>你家</li> <li>我家</li> <li>如家</li> </ul> <script> window.onload = function(){ let btn = document.getElementById('btn') let oUl = document.getElementsByTagName('ul')[0]; btn.onclick=function () { let oLi = document.createElement('li'); oLi.innerHTML = '全家' oUl.appendChild(oLi); //新增li } function beenChecked(e) { e.target.classList.add('checked') } function notChecked(e) { e.target.classList.remove('checked') } oUl.addEventListener('mouseover',beenChecked) // 默認事件冒泡 oUl.addEventListener('mouseout',notChecked) } </script>
四、缺點
1.事件的委托基於冒泡,對於onfocus和onblur事件不支持。
2.層級過多,冒泡過程中,可能會被某層阻止掉(建議就近委托)
只要事件不支持冒泡或者途中有 event.stopPropagation() 等,那么委托就會失敗,所以並不適用直接在document上進行委托。