js事件委托详解

先说事件流

js的事件流分为3个阶段:捕获、目标、冒泡。即事件来了,先从上到下传播(捕获),到达目标节点(目标),而后在往上传播(冒泡)。看下图:html

图片描述

咱们能够在绑定事件的时候指定指是在哪一个阶段触发事件,element.addEventListener(event, function, useCapture),useCapture默认为false,即默认在冒泡阶段触发事件,来作个测试:node

demo长这样:
图片描述函数

html:性能

<div id='wraper'>
        wraper
        <ul>
            <li>li1</li>
            <li>li2</li>
            <li id='li3'>
                li3
                <span>span</span>
            </li>
        </ul>
    </div>

js:测试

document.getElementById('wraper').addEventListener('click',function(e){
    console.log('wraper')
},false)

document.getElementById('li3').addEventListener('click',function(e){
    console.log('li3')
},false)

document.getElementsByTagName('span')[0].addEventListener('click',function(){
    console.log('span')
},false)

能够看到,这里全是在冒泡阶段触发事件,所以结果为:span li3 wraper 这样的顺序(从下到上),以此类推,若是所有设置为捕获阶段触发事件呢?顺序确定就反过来了,继续看下面:优化

document.getElementById('wraper').addEventListener('click',function(e){
    console.log('wraper')
},true)

document.getElementById('li3').addEventListener('click',function(e){
    console.log('li3')
},true)

document.getElementsByTagName('span')[0].addEventListener('click',function(){
    console.log('span')
},true)

结果为:wraper li3 span
同时还能够测试,某一个事件在捕获阶段是优先触发于冒泡阶段的:spa

document.getElementById('wraper').addEventListener('click',function(e){
    console.log('wraper')
},false)

document.getElementById('li3').addEventListener('click',function(e){
    console.log('li3')
},true)

document.getElementsByTagName('span')[0].addEventListener('click',function(){
    console.log('span')
},false)

结果为:li3 span wrapercode

从需求出发

来了这样一个需求:在上面的demo中,要给ul下的每一个li绑定一个事件,在点击以后触发。
若是是每一个li都去单独绑定事件?明显不科学,毕竟去拿li列表也是毕竟消耗性能的,同时每一个事件绑定的回调函数也会占用大量的内存。
你可能会说,个人元素很少,上面的消耗无所谓。那若是有动态插入的元素呢?
因而委托就能够用上了。htm

document.getElementById('wraper').addEventListener('click', function (e) {
  var target = e.target
  if (target.nodeName.toLocaleLowerCase() === 'li') {
    console.log(target.innerHTML);
  }
});

这里的e.target指的时候鼠标最后点击的元素。在这个demo中,点击深红色的span,e.target就指的是span,若是点击li3且不在红色的span中,那么e.target指li3。
有一个问题就是若是匹配的元素须要更具体一些,好比class为li-test的某个li,就须要作优化处理了。后面专门来一篇文章讲。blog

相关文章
相关标签/搜索