事件冒泡

当触发一个节点的事件是,会从当前节点开始,依次触发其祖先节点的同类型事件,直到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属性。

最后修改:2020 年 03 月 27 日
如果觉得我的文章对你有用,请随意赞赏