由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和冒泡阶段,会依次检查途径的每一个节点,若是该节点注册了相应的监听函数,则执行监听函数。如下面的HTML结构为例:javascript
<div id="parentdiv"> 父亲 <div id="childdiv">孩子</div> </div>
执行的流程应该是这样的:java
下面是一组例子,分别点击孩子节点能够清楚的看到第三个参数的影响:web
父亲浏览器
孩子框架
父亲节点的监听函数在捕获阶段执行:异步
var parent1 = document.getElementById(‘parentdiv1′); var child1 = document.getElementById(‘childdiv1′); parent.addEventListener(‘click’,function(){alert(‘父亲被点击了’);},true);//第三个参数为true child.addEventListener(‘click’,function(){alert(‘孩子被点击了’);},false);
父亲函数
孩子
父亲节点的监听函数在冒泡阶段执行:性能
var parent2 = document.getElementById(‘parentdiv2′); var child2 = document.getElementById(‘childdiv2′); parent.addEventListener(‘click’,function(){alert(‘父亲被点击了’);},false);//第三个参数为false child.addEventListener(‘click’,function(){alert(‘孩子被点击了’);},false);
父亲this
孩子spa
父亲节点的监听函数在捕获冒泡阶段都执行:
var child3 = document.getElementById(‘childdiv3′); parent.addEventListener(‘click’,function(){alert(‘父亲被点击了’);},true);//第三个参数为true parent.addEventListener(‘click’,function(){alert(‘父亲被点击了’);},false);//第三个参数为false child.addEventListener(‘click’,function(){alert(‘孩子被点击了’);},false);
若是不想让事件向上冒泡,能够在监听函数中调用event.stopPrapagation()来完成,这样父亲节点就捕捉不到该事件了。在实际的开发中,这一用处仍是挺多的。
知道了事件的捕获冒泡机制,咱们能够利用它来实现更方便的程序控制,事件委托即是最典型的应用之一。下面来讲说javascript中的事件委托机制。什么叫委托呢?想一想咱们现实生活中,本身不想干的事,让别人来帮忙完成,这就是把事情“委托”给别人。Javascript的事件委托机制也是这个道理,原本一个监听函数要处理节点a触发的事件,如今把这个监听函数绑定到节点a的父层节点上,让它的父辈来完成事件的监听,这样就把事情“委托”了过去。在父辈元素的监听函数中,可经过event.target属性拿到触发事件的原始元素,而后再对其进行相关处理。
那这样作有什么好处呢?最大的用处即是监听动态增长的元素。好比咱们如今有这样的需求,点击下面每一个列表项弹出各自的内容,如今随着web应用的盛行,网页中使用异步请求来动态加载节点已经变的很广泛,因此咱们点击下方的按钮要在列表中增长一项,而且点击新增长的节点也要弹出内容。HTML结构以下:
<ol id="olist"> <li>列表内容1</li> <li>列表内容2</li> <li>列表内容3</li> <li>列表内容4</li> <li>列表内容5</li> </ol>
若咱们使用以前的监听器绑定方式,须要遍历全部的li元素并监听,代码应该是这样的:
var listArray = document.getElementById('olist').childNodes; for(var i=0;i<listArray.length;i++){ listArray[i].addEventListener('click',function({ alert(this.innerText); }); }
运行效果以下:
列表内容1
列表内容2
列表内容3
列表内容4
列表内容5
能够发现当新增元素后,点击它并无弹出内容。那是固然的了,由于咱们并无给新增的元素绑定监听器,为了实现点击新增元素也弹出内容,咱们不得不在每次新增一个元素后,再进行一次绑定。加一个绑一个,加一个绑一个,累不累啊!你不累浏览器都累了!这样作致使的性能开销是可想而知的,并且浏览器还要维系n多元素与应的监听函数的映射关系,会占用大量内存。
面对这样拖沓冗杂的代码,你是否是已经不能忍,来看看使用事件委托的效果,代码以下:
var olist = document.getElementById('olist'); olist.addEventListener('click',function(){ alert(event.target.innerText); },false);
看看实际运行的效果:
列表内容1
列表内容2
列表内容3
列表内容4
列表内容5
咱们并未给li元素绑定任何监听器,而是监听它的父元素ul,等到事件冒泡上来的时候,在处理函数中经过event.target得到触发事件的li元素,进行相关处理。这样作的好处是显而易见的,首先只进行了一次监听器的绑定,浏览器轻松,其次动态增长元素后你也没必要要再绑定监听器,你也轻松。正所谓你们好才是真的好!
本篇的基本内容就介绍完了,你是否是感受有点奇妙,我平时写程序的时候没关心这些也仍然能完成工做呀?那我就得问你是否是使用js框架,使用jQuery了,事实上,jQuery提供的on、live等方法就已经对事件委托进行了封装,为委托机制的推广悄悄作了底层贡献,你没感受到而已。jQuery中的各类事件监听方式也须要咱们有一个清楚的了解,才能正确的使用,高效的完成工做。这些内容将放在下一篇介绍。