📖事件委托与事件冒泡

事件委托

 * 什么是事件委托?
  – 利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行
 * 为什么要用事件委托
  – 正常来说直接给DOM设置事件处理程序就好了,但是有很多DOM需要设置事件处理,比如有100个li需要设置,这时候因为需要与DOM节点进行交互访问DOM次数就变多,就会延长整个页面的交互就绪时间;这时候用到事件委托,将所有事件放到js程序里这时候与DOM的操作就只需要进行一次就够了
 * 事件委托的原理
  – 事件委托是利用事件冒泡原理来实现的
 * 事件委托的优点
  – 大量减少内存占用,减少事件注册
  – 实现在新增子项时无需在重新对其绑定(动态事件绑定)

案例展示

 一般的方法案例
  该方法进行多次DOM操作,首先获取到ul在通过遍历获取到所有的li,在给所以li绑定一个点击事件

  1. <ul id="new_ul">
  2. <li>1111</li>
  3. <li>2222</li>
  4. <li>3333</li>
  5. <li>4444</li>
  6. <li>5555</li>
  7. </ul>
  1. window.onload = function(){
  2. let newul = document.getElementById('new_ul');
  3. let newli = newul.getElementsByTagName('li');
  4. for(let i = 0;i < newli.length;i++){
  5. newli[i].onclick =function(){
  6. alert(i+1);
  7. }
  8. }
  9. }

 使用事件委托
  直接找到ul并绑定事件,当点击li时事件冒泡,因为ul有点击事件所以会触发

  1. window.onload = function(){
  2. let newul = document.getElementById('new_ul');
  3. newul.onclick =function(){
  4. alert('a');
  5. }
  6. }

 那么问题来了如果我想事件代理的效果跟直接点击节点一样怎么办
 Event对象提供了一个属性:target,可以返回事件的目标节点,target就可以表示为当前的事件操作的dom,但是不是真正操作dom
 兼容性:标准浏览器用ev.target,IE浏览器用event.srcElement
 利用target获取的是节点,我们还需要获得名称所以用nodeName,nodeName获取的是大写在进行小写化利用toLowerCase()转化成小写

  1. window.onload = function(){
  2. let newul = document.getElementById('new_ul');
  3. newul.onclick =function(ev){
  4. let ev = ev || window.event;
  5. let target = ev.target || event.srcElement;
  6. if(target.nodeName.toLowerCase() == 'li'){
  7. alert(target.innerHTML);
  8. }
  9. }
  10. }

 增加新节点,新节点会有事件效果吗

  1. <input type="" name="" value="" id='zhi'>
  2. <input type="button" name="" value="增加" id='butt'>
  3. <ul id="new_ul">
  4. <li>1111</li>
  5. <li>2222</li>
  6. <li>3333</li>
  7. <li>4444</li>
  8. <li>5555</li>
  9. </ul>
  1. window.onload = function(){
  2. let butt = document.getElementById('butt');
  3. let newul = document.getElementById('new_ul');
  4. let newli = newul.getElementsByTagName('li');
  5. let num = newli.length;
  6. newul.onclick = function(ev){
  7. var ev = ev||window.event;
  8. let target = ev.target || event.srcElement;
  9. if(target.nodeName.toLowerCase() == 'li'){
  10. alert(target.innerHTML);
  11. }
  12. }
  13. butt.onclick = function(){
  14. let xinli = document.createElement('li');
  15. let zhi = document.getElementById('zhi').value;
  16. xinli.innerHTML = zhi;
  17. newul.appendChild(xinli);
  18. }
  19. }

通过实验证明新增的li是会触发ul的事件的

事件委托的注意事项

  – 使用“事件委托”时,并不是说把事件委托给的元素越靠近顶层就越好。事件冒泡的过程也需要耗时,越靠近顶层,事件的”事件传播链”越长,也就越耗时。如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失

事件冒泡

  – 当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window

  1. <ul onclick="alert('ul_click')">
  2. <li onclick="alert('li_click')"><a href="" id="li_a">a</a></li>
  3. </ul>
  1. //正常的事件冒泡,这个会一直往上冒泡
  2. window.onload = function(){
  3. let lia = document.getElementById('li_a');
  4. lia.onclick = function(){
  5. alert("a");
  6. }
  7. }
  1. //阻止事件冒泡
  2. window.onload = function(){
  3. let lia = document.getElementById('li_a');
  4. lia.onclick = function(){
  5. alert("a");
  6. event.stopPropagation();
  7. }
  8. }

阻止事件冒泡的方法有很多种,本文只采用了方便快捷的一种

方法总结

  – var ev = ev||window.event; 兼容性写法
  – let target = ev.target || event.srcElement; 获取目标节点
  – toLowerCase() 将字母小写
  – appendChild() 插入节点
  – target.nodeName 目标节点的名称(大写)
  – event.stopPropagation(); 阻止事件冒泡到DOM树上

标签

🧐发表评论

请将下面的 放到右边的灰色圆圈中