JS事件委托(事件代理,dom2级事件)
一、前言
说实话,真问我什么是事件委托,我肯定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上进行委托。