JS的事件冒泡、事件捕获和事件委托

事件流:它有三个阶段,分别为事件捕获、目标事件、事件冒泡

事件冒泡会从当前触发的事件目标一级一级往上传递,依次触发,直到document为止。
事件捕获会从document开始触发,一级一级往下传递,依次触发,直到真正事件目标为止。
事件委托依靠的就是事件冒泡和捕获的机制

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <style type="text/css">
        #box1 { width: 300px; height: 300px; background: blueviolet; }
        #box2 { width: 200px; height: 200px; background: aquamarine; }
        #box3 { width: 100px; height: 100px; background: tomato; }
        div { overflow: hidden; margin: 50px auto; }
    </style>
    <body>
        <div id="box1">
            <div id="box2">
                <div id="box3"></div>
            </div>
        </div>
        <script>
            function sayBox3() {
                console.log('你点了最里面的box');
            }
            function sayBox2() {
                console.log('你点了最中间的box');
            }
            function sayBox1() {
                console.log('你点了最外面的box');
            }
            // 事件监听,第三个参数是布尔值,默认false,false是事件冒泡,true是事件捕获
            document.getElementById('box3').addEventListener('click', sayBox3, false);
            document.getElementById('box2').addEventListener('click', sayBox2, false);
            document.getElementById('box1').addEventListener('click', sayBox1, false);

        </script>
    </body>
</html>

在这里插入图片描述
我们仅仅是点击了红色的box,但是绿色和紫色的box也被触发了打印事件,触犯顺序是 红色>绿色>紫色,这种现象就是事件冒泡了。

我们再试试事件捕获,把上面代码里监听事件的第三个参数改为true,然后点击红色的box:

在这里插入图片描述

我们还是只点击最中间的红色box,和上一次一样,也是三个box都触发了事件,但是顺序反过来了,紫色>绿色>红色,这种现象称为事件捕获。
通过上面的例子,应该很容易就理解了事件冒泡和事件捕获,我们平时都是默认冒泡的,冒泡是一直冒到document根文档为止。

阻止冒泡的方法:

function() {
    // IE里阻止冒泡
    window.event.cancelBubble = true;
    // IE里获取事件源的id
    //var srcID = window.event.srcElement.id;
    //ie阻止默认事件
    //window.event.returnValue = false 
}
function(event) {
    // 非IE里阻止冒泡
    event.stopPropagation();
    // 非IE里获取事件源的id
   // var srcID = event.target.id;
   //非IE阻止默认事件,使用preventDefault
}

现在来谈谈事件委托,事件委托又称之为事件代理,我们通过一个通俗的例子来解释:

有三个同事预计会在周一收到快递,为了签收快递,有两种办法:1.三个人在公司门口等快递;2.委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收(可以给暂时不存在的节点也绑定上事件)。

现在有一个ul,ul里又有100个li,我想给这100个li都绑定一个点击事件,我们一般可以通过for循环来绑定,但是要是有1000个li呢? 为了提高效率和速度,所以我们这时可以采用事件委托,只给ul绑定一个事件,根据事件冒泡的规则,只要你点了ul里的每一个li,都会触发ul的绑定事件,我们在ul绑定事件的函数里通过一些判断,就可以给这100li都触发点击事件了。

<body>
    <ul id="isUl">
        <li id="li01">1</li>
        <li id="li02">2</li>
        <li id="li03">3</li>
    </ul>
    <script>
        function clickLi01() {
            alert('你点击了第1个li');
        }
        function clickLi02() {
            alert('你点击了第2个li');
        }
        function clickLi03() {
            alert('你点击了第3个li');
        }
        document.getElementById('isUl').addEventListener('click', function(event) {
            var srcID = event.target.id;
            if(srcID == 'li01'){
                clickLi01();
            }else if(srcID == 'li02') {
                clickLi02();
            }else if(srcID == 'li03') {
                clickLi03();
            }
        });
    </script>
</body>

这就是所谓的事件委托,通过监听一个父元素,来给不同的子元素绑定事件,减少监听次数,从而提升速度。

如果元素被阻止冒泡了,千万别去用事件委托的方式监听事件,因为事件委托的原理是利用事件冒泡,当冒泡被阻止,就无法监听了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值