事件委托或者事件冒泡其实都是基于js的事件流机制产生的。在说时间委托和事件代理之前,我们先来了解下事件流,搞懂事件流,也就知道了事件委托,事件代理是怎么回事了,下面上个图(摘自https://www.cnblogs.com/wxf-h/)
事件流图如下:
由图看,当一个事件被触发时发生了什么:
1.整个事件流程是从window开始又回到window的过程。
2.整个事件流分为三个阶段,1.从window开始向下捕获(1~5)。2.确定事件目标元素(5,6)。3.向上冒泡过程(7-10)。
这也就引用出来,事件冒泡和捕获的原理,因为事件流是从window开始,再回到window。所以会产生捕获和冒泡。
下面写一段代码解释下:
<body>
<div class="a">
a
<div class="b">b</div>
</div>
</body>
<script type="text/javascript">
var a=document.getElementsByClassName("a")[0];
var b=document.getElementsByClassName("b")[0];
a.oclick=function(){ //此处绑定两个a的**Dom0**级事件
console.log("a");
}
a.onclick=function(){
console.log("a2");
}
b.onclick=function(){
console.log("b");
}
</script>
此时点击b元素,运行结果输出:
b
a2
上面的例子是 ”Dom0“ 级事件,在Dom0级事件中一个元素相同的事件只能绑定一次如(onclick),并且绑定的是最后绑定的那个事件,这个有点像jquery中的html方法一样,后面的会覆盖掉前面的内容一样。在Dom0级事件里只有事件冒泡没有事件捕获
此处流程就是首先进行从window捕获 ,捕获到事件元素触发事件,在冒泡触发到window。这就是事件触发的流程,由此可以看出,事件代理是怎么形成的了。
在Dom2级事件里支持事件冒泡和事件捕获
a.addEventListener("click",function(){
console.log("a");
},false);
a.addEventListener("click",function(){
console.log("a-2");
},false);
b.addEventListener("click",function(){
console.log("b");
},false);
执行结果
b
a
a-2
这里是发生了事件冒泡,点击b,先执行了b后输出了a和a-2,同时可以看出Dom2级事件是支持添加同名事件的按照先后顺序执行。addEventListener是Dom2里添加事件监听的写法可以接受三个参数,第一个参数是事件名称,第二个是事件处理函数,第三个参数是布尔值true是设置事件捕获,false是设置事件冒泡,默认情况下是false。IE里面添加监听事件是attachEvent但是IE不支持事件捕获,所以attachEvent只有前两个参数,不能设置true和false,同时事件名也要加上on。比如:addEventListener的单击事件是click,而attachEvent的单击事件是onclick。有添加监听事件就有移除监听事件,与addEventListener相对的是removeEventListener,与attachEvent相对应的是deatchEvent这两个写法与上面类似,需要注意的是移除事件时要同时删除事件名和对应的方法。为了解决和IE的兼容问题同城会将两种写法封装成一个函数进行调用,因为IE不支持事件捕获,所以尽量使用事件冒泡以解决兼容问题。
事件代理:
事件代理就是利用事件冒泡的原理来进行的,假如你的dom层级ul<li<a ,那么他点击a的时候,事件触发流程是a<li<ul,如果所有a的事件都是类似,可以最终绑定到最外层ul上同意代理。下面以ul<li为例。
<ul id="a">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
<script>
var aLi = document.getElementById('a').children;
for (var i=0;i<aLi.length;i++) { //传统方法是这么写的 循环绑定事件
aLi[i].onclick= function() {
this.style.background = 'red';
}
}
//事件代理写法
var ul=document.getElementById('a');
ul.onclicl=function(ev){
var ev = ev || window.event;
var oLi = ev.srcElement || ev.target;
oLi.style.background = 'red'
}
</script>
也还可用事件代理进行绑定
element.addEventListener(event, function, useCapture)
event : (必需)事件名,支持所有 DOM事件 。
function:(必需)指定要事件触发时执行的函数。
useCapture:(可选)指定事件是否在捕获或冒泡阶段执行。true,捕获。false,冒泡。默认false。