事件委托:利用冒泡的原理,把事件加到父级上,触发执行效果。
例子:
<ul id="ull">
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
//一般写法
var li=document.getElementsByTagName("li");
for(var i=0;i<li.length;i++){
li[i].onclick=function () {
console.log("1")
}
}
//缺点:绑定多个事件,并且如果后续有新添加的节点li,需要重新绑定onclick事件
//事件代理
var ull=document.getElementById("ull");
ull.addEventListener("click",function (e) {
var target=e.target;
if(target.nodeName.toUpperCase()=="LI") {
console.log("1")
stopPropagation(e)//阻止继续向上冒泡
}
});
事件冒泡:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。(target-body-html-document)
<div id="div2">
<ul id="ull">
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
</div>
假设给div和li都绑定了click事件,那么当点击li时,会先后(从内到外)触发这两个click事件,如果不想要这样的结果,那么就需要阻止冒泡
//阻止事件冒泡
function stopPropagation(e) {
if (e.stopPropagation) {
e.stopPropagation();//Firefox
} else {
e.cancelBubble = true;//IE
}
}
事件捕获:与事件冒泡的顺序相反(IE没有事件捕获)
W3C模型
W3C模型是将两者进行中和,在W3C模型中,任何事件发生时,先从顶层开始进行事件捕获,直到事件触发到达了事件源元素。然后,再从事件源往上进行事件冒泡,直到到达document。
一般的绑定事件方式,如:onclick,采用的是冒泡方式。
但我们可以选择事件处理函数在哪一个阶段被调用。
addEventListener有三个参数:
element.addEventListener(event, function, useCapture)
//第三个参数默认值是false,表示在事件冒泡的阶段调用事件处理函数,如果参数为true,则表示在事件捕获阶段调用处理函数
<div id="div1" style="width: 500px;background-color: yellow">
<div id="div2" style="width: 50%;background-color: aqua;margin: 0 auto">
<ul id="ull" style="width: 50%;background-color: coral;margin: 0 auto">
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
</div>
</div>
//事件捕获
var div1=document.getElementById("div1");
var div2=document.getElementById("div2");
var ull=document.getElementById("ull");
div2.addEventListener("click",function () {
console.log('div2')
},true); //捕获时执行
div1.addEventListener("click",function () {
console.log('div1')
});//
ull.addEventListener("click",function () {
console.log('ull')
});
//点击ul,依次打印出div2,ull,div1
参考:
https://segmentfault.com/a/1190000000749838
http://www.jb51.net/article/42492.htm