JS事件委托模式

前沿

这段时间在做一个论坛网站,由于文章需要动态添加在列表后面,添加之后就发现一个问题。之前在列表中用for给列表元素addEventListener了一些监听事件,在后面动态添加的元素中没有生效。这是因为,在后面动态加入的dom中没有执行addEventListener事件,当然我们也可以在动态添加完后再给他们添加一次监听事件,这有可能会出现一个问题,就是前面的元素可能会重复添加监听事件,导致执行多次事件处理。这不断操作DOM,也会造成巨大的性能损耗。所以这里我们引用了----事件委托。
 

事件委托

将子元素的事情委托给父元素,然后通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件源的某种特性来执行相应的业务逻辑。

 

处理动态添加事件

如果我们按照正常的for循环添加事件绑定,如下 代码片.

// An highlighted block
<body>
    <ul>
        <li>s1</li>
        <li>s2</li>
        <li>s3</li>
        <li>s4</li>  
    </ul>
    <button id='add'>添加属性</button>
    <script>
        (function(){
            let lis = document.getElementsByTagName('li');
            let addBtn = document.getElementById("add");
            let ul = document.getElementsByTagName('ul');
            for(let i=0,len=lis.length;i<len;i++){
                lis[i].addEventListener('click',()=>{
                    alert(`你点到我了!${lis[i].innerText}`);
                })
            }
            addBtn.addEventListener('click',()=>{
                let li = document.createElement('li');
                li.innerHTML = "新增元素";
                ul[0].appendChild(li);
            })
        })()
    </script>
</body>

这里就会出现一个问题,前面原先有的li点击是可以触发处理事件,点击添加按钮后动态添加的li却木有绑定上点击事件。
这时我们可以将子元素的事件委托给父元素去绑定执行,这样我们就无需关心子元素的修改。我们将上诉代码修改为

<body>
    <ul>
        <li>s1</li>
        <li>s2</li>
        <li>s3</li>
        <li>s4</li>  
    </ul>
    <button id='add'>添加属性</button>
    <script>
        (function(){
            let addBtn = document.getElementById("add");
            let ul = document.getElementsByTagName('ul');
            ul[0].addEventListener('click',(e)=>{
                 e = e || window.event;
                let tar = e.target || e.srcElement;
                if(tar.nodeName.toLowerCase()=='li'){               
                        alert(`你点到我了!${tar.innerText}`);
                }
            })
            addBtn.addEventListener('click',()=>{
                let li = document.createElement('li');
                li.innerHTML = "新增元素";
                ul[0].appendChild(li);
            })
        })()
    </script>
</body>

这样我们就无需关系ul后面添加多少个li,都依旧能触发相应处理。

 

处理内存外泄问题

像老版本的IE浏览器,其用的是计数式垃圾回收机制,使得一些对Dom元素引用没有显性清除的数据会遗留在内存中,除非关闭浏览器,否则无法清除。例如

<div id="btn_container">
        <button id="btn">demo</button>
</div>
var g = function(id){return document.getElementById(id);}
        g('btn').onclick=function(){
            g('btn_container').innerHTML = "触发了事件!";
        }

这时点击btn时,就会触发事件处理把btn按钮给覆盖,但是其click事件没有被清除,就会泄露到内存中,当然可以将其设为null
g(‘btn’).οnclick=null;更好的办法就是使用委托模式。

g('btn_container').onclick=function(e){
   //获取触发事件
   var target = e && e.target || window.event.srcElement;
   //判断触发事件元素id是否为btn
   if(target.id==='btn'){
      //重置父元素内容
      g('btn_container').innerHTML = '触发了事件';
   }
}

 
当然委托模式不仅仅有这些作用,在后端可以处理事件分发的问题,将多个请求打包成一个节约多次请求对时间的开销。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值