先说事件流js的事件流分为3个阶段:捕获、目标、冒泡。即事件来了,先从上到下传播(捕获),到达目标节点(目标),然后在往上传播(冒泡)。看下图:我们可以在绑定事件的时候指定指是在哪个阶段触发事件,element.addEventListener(event, function, useCapture),useCapture默认为false,即默认在冒泡阶段触发事件,来做个测试: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 同时还可以测试,某一个事件在捕获阶段是优先触发于冒泡阶段的: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 wraper从需求出发来了这样一个需求:在上面的demo中,要给ul下的每个li绑定一个事件,在点击之后触发。如果是每个li都去单独绑定事件?明显不科学,毕竟去拿li列表也是毕竟消耗性能的,同时每个事件绑定的回调函数也会占用大量的内存。你可能会说,我的元素不多,上面的消耗无所谓。那如果有动态插入的元素呢?于是委托就可以用上了。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,就需要做优化处理了。后面专门来一篇文章讲。
