事件冒泡
当触发一个节点的事件是,会从当前节点开始,依次触发其祖先节点的同类型事件,直到DOM根节点。简易理解自内向外,从自己到祖先。
事件捕获
当触发一个节点的事件时,会从DOM根节点开始,依次触发其祖先节点的同类型事件,直到当前节点自身。简易理解自外向内,从祖先到自己。
什么时候事件冒泡?什么时候事件捕获?
1.当使用addEventListener绑定事件,第三个参数传为true时表示事件捕获;
2.除此之外的所有事件绑定均为事件冒泡。
阻止冒泡
阻止事件冒泡:
① IE10之前,e.cancelBubble = true;
② IE10之后,e.stopPropagation();
阻止默认事件:
① IE10之前:e.returnValue = false;
② IE10之后:e.preventDefault();
事件冒泡,捕获代码
HTML 代码
#child {
width: 500px;
height: 500px;
background-color: red
}
<div id="demo">
<div id="parent">
<div id="child"></div>
</div>
</div>
JavaScript代码
var demo = document.getElementById('demo');
var parent = document.getElementById('parent');
var child = document.getElementById('child');
demo.addEventListener("click",function(ev) {
console.log("我是demo冒泡");
});
parent.addEventListener("click",function(ev) {
console.log("我是parent冒泡");
});
child.addEventListener("click",function(ev) {
console.log("我是child冒泡");
});
输出结果:
我是child冒泡
我是parent冒泡
我是demo冒泡
如果修改一下,
demo.addEventListener("click",function(ev) {
console.log("我是demo冒泡");
},true);
输出结果:
我是demo冒泡
我是child冒泡
我是parent冒泡
加入true成为事件捕获,从祖先节点开始,所以输出demo。
停止冒泡的话,在
child.addEventListener("click",function(ev) {
console.log("我是child冒泡");
ev.stopPropagation();
});
输出结果:
我是child冒泡
事件委托
事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。
事件委托的特点
1.可以大量节省内存占用,减少事件注册
2.实现当新增子对象时无需再次对其绑定事件,实现动态内容很方便
举例:
最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加。
HTML代码
<ul id="ul1">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
<button id="btn">新增节点</button>
Javascript代码
window.onload = function(){
var btn = document.getElementById("btn");
var ulList = document.getElementById("ul1");
//新增li节点
btn.onclick = function() {
var addli = document.createElement('li');
addli.innerHTML='新增li';
ulList.appendChild(addli);
}
//执行事件委托
ulList.onclick = function(e) {
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() =="li"){
console.log(target.innerHTML)
}
}
}
关于代码
var ev = ev || window.event; 等同于var e=event?event||window.event;
为了实现浏览器兼容,原理是ie的document对象有一个all属性,它的里面存放了页面的所有标签,而其它浏览器是没有的,所以在ie中,事件对象的传播会绑定在全局的windows上,所以ie浏览器肯定是都支持window.event的。
而其他标准浏览器,通常使用给事件处理阐述传递的事件对象,直接写event它是支持的。
var target = ev.target || ev.srcElement;
这个就好理解了,IE中,event对象有srcElement属性,但是没有target属性。Firefox中,event对象有target属性,但是没有srcElement属性。
2 条评论
作者的才华横溢,让这篇文章成为了一篇不可多得的艺术品。
文章结构紧凑,层次分明,逻辑严密,让人一读即懂。