📖事件委托与事件冒泡
事件委托
* 什么是事件委托?
– 利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行
* 为什么要用事件委托
– 正常来说直接给DOM设置事件处理程序就好了,但是有很多DOM需要设置事件处理,比如有100个li需要设置,这时候因为需要与DOM节点进行交互访问DOM次数就变多,就会延长整个页面的交互就绪时间;这时候用到事件委托,将所有事件放到js程序里这时候与DOM的操作就只需要进行一次就够了
* 事件委托的原理
– 事件委托是利用事件冒泡原理来实现的
* 事件委托的优点
– 大量减少内存占用,减少事件注册
– 实现在新增子项时无需在重新对其绑定(动态事件绑定)
案例展示
一般的方法案例
该方法进行多次DOM操作,首先获取到ul在通过遍历获取到所有的li,在给所以li绑定一个点击事件
<ul id="new_ul"> <li>1111</li> <li>2222</li> <li>3333</li> <li>4444</li> <li>5555</li> </ul>
window.onload = function(){ let newul = document.getElementById('new_ul'); let newli = newul.getElementsByTagName('li'); for(let i = 0;i < newli.length;i++){ newli[i].onclick =function(){ alert(i+1); } } }
使用事件委托
直接找到ul并绑定事件,当点击li时事件冒泡,因为ul有点击事件所以会触发
window.onload = function(){ let newul = document.getElementById('new_ul'); newul.onclick =function(){ alert('a'); } }
那么问题来了如果我想事件代理的效果跟直接点击节点一样怎么办
Event对象提供了一个属性:target,可以返回事件的目标节点,target就可以表示为当前的事件操作的dom,但是不是真正操作dom
兼容性:标准浏览器用ev.target,IE浏览器用event.srcElement
利用target获取的是节点,我们还需要获得名称所以用nodeName,nodeName获取的是大写在进行小写化利用toLowerCase()转化成小写
window.onload = function(){ let newul = document.getElementById('new_ul'); newul.onclick =function(ev){ let ev = ev || window.event; let target = ev.target || event.srcElement; if(target.nodeName.toLowerCase() == 'li'){ alert(target.innerHTML); } } }
增加新节点,新节点会有事件效果吗
<input type="" name="" value="" id='zhi'> <input type="button" name="" value="增加" id='butt'> <ul id="new_ul"> <li>1111</li> <li>2222</li> <li>3333</li> <li>4444</li> <li>5555</li> </ul>
window.onload = function(){ let butt = document.getElementById('butt'); let newul = document.getElementById('new_ul'); let newli = newul.getElementsByTagName('li'); let num = newli.length; newul.onclick = function(ev){ var ev = ev||window.event; let target = ev.target || event.srcElement; if(target.nodeName.toLowerCase() == 'li'){ alert(target.innerHTML); } } butt.onclick = function(){ let xinli = document.createElement('li'); let zhi = document.getElementById('zhi').value; xinli.innerHTML = zhi; newul.appendChild(xinli); } }
通过实验证明新增的li是会触发ul的事件的
事件委托的注意事项
– 使用“事件委托”时,并不是说把事件委托给的元素越靠近顶层就越好。事件冒泡的过程也需要耗时,越靠近顶层,事件的”事件传播链”越长,也就越耗时。如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失
事件冒泡
– 当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window
<ul onclick="alert('ul_click')"> <li onclick="alert('li_click')"><a href="" id="li_a">a</a></li> </ul>
//正常的事件冒泡,这个会一直往上冒泡 window.onload = function(){ let lia = document.getElementById('li_a'); lia.onclick = function(){ alert("a"); } }
//阻止事件冒泡 window.onload = function(){ let lia = document.getElementById('li_a'); lia.onclick = function(){ alert("a"); event.stopPropagation(); } }
阻止事件冒泡的方法有很多种,本文只采用了方便快捷的一种
方法总结
– var ev = ev||window.event; 兼容性写法
– let target = ev.target || event.srcElement; 获取目标节点
– toLowerCase() 将字母小写
– appendChild() 插入节点
– target.nodeName 目标节点的名称(大写)
– event.stopPropagation(); 阻止事件冒泡到DOM树上
🧐发表评论