JS事件流

1.事件:事件是指JS与HTML的交互。

2.事件流:IE的事件流是指事件冒泡,Netscape的事件流是指事件捕获。(Netscape是网景通信公司,曾是一家美国的计算机服务公司,曾是IE的竞争对手,在1998年11月被AOL收购)。事件冒泡是指自下而上,事件捕获是指自上而下。

3.DOM事件处理:DOM事件处理分为4个级别,分别是DOM0,DOM1,DOM2,DOM3,其中DOM1级事件处理标准中没有定义相关的内容,所以就没有所谓的DOM1事件处理。DOM3级事件处理是在DOM2级事件处理的基础上添加了更多的事件类型。下面我们就从DOM0和DOM2级事件处理来讲解JS事件流。DOM2把事件冒泡和事件捕获进行了结合,即事件流为:事件捕获阶段、处于目标阶段、事件冒泡阶段。

(1)DOM0级事件处理有两种事件绑定方法。第一是内联模型,第二是脚本模型。

内联模型是指直接在dom节点上绑定事件,比如<div οnclick="btnClick"></div>,而脚本模型就是我们最常见的,如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
     
        #son {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
    <script>
        window.onload = function () {
            let oSon = document.getElementById("son");

            oSon.onclick = function () {
                alert("son")
            };
            oSon.onclick = function () {
                alert("son again");
            }

        }
    </script>
</head>
<body>
    <div id="son"></div>
</body>
</html>

在上面这个代码中,给son这个div绑定了两次点击事件,当点击这个div的时候,只会弹出son again。这是因为后面的事件把前面的事件给覆盖掉了。

再看下面这个代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #father {
            width: 100px;
            height: 100px;
            background: red;
        }
        #son {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
    <script>
        window.onload = function () {
            let oSon = document.getElementById("son");
            let oFather = document.getElementById("father");
            oSon.onclick=function(){
                alert("son")
            };
            oFather.onclick=function(){
                alert("father")
            }
        }
    </script>
</head>
<body>
    <div id="father">
        <div id="son"></div>
    </div>
</body>
</html>

结果是先弹出son,再弹出father,这就是所谓的事件冒泡,但是却不能事件捕获(即只能自下而上,而不能自上而下)。

可以发现DOM0级事件处理存在的问题是:事件覆盖和不能事件捕获。当然它的优点是:极好的跨浏览器优势,会以最快的速度绑定。

(2)DOM2级事件处理就可以很好的处理DOM0级事件的问题。

首先我们处理一下DOM0级中的事件冲突:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #son {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
    <script>
        window.onload = function () {
            let oSon = document.getElementById("son");
            let oFather = document.getElementById("father");
            //通过addEventListener来绑定事件,其中第三个参数是个布尔型的,false代表事件冒泡,true代表事件捕获,在这里由于没有涉及到事件流,所以取什么都行
            oSon.addEventListener("click", function () {
                alert("son")
            }, false);
            oSon.addEventListener("click", function () {
                alert("son again")
            }, false);
        }
    </script>
</head>

<body>

    <div id="son"></div>

</body>

</html>

先弹出son,再弹出son again。

接下来我们去解决事件捕获。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #father {
            width: 100px;
            height: 100px;
            background: red;
        }

        #son {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
    <script>
        window.onload = function () {
            let oSon = document.getElementById("son");
            let oFather = document.getElementById("father");
            //通过addEventListener来绑定事件,其中第三个参数是个布尔型的,false代表事件冒泡,true代表事件捕获
            oSon.addEventListener("click",function(){
                alert("son")
            },true)
            oFather.addEventListener("click",function(){
                alert("father")
            },true)
        }
    </script>
</head>

<body>
    <div id="father">
        <div id="son"></div>
    </div>
</body>
</html>

这次是先弹出father,再弹出son。这样就实现了事件捕获。当然如果想实现事件冒泡,将true改为false即可。

3.如何阻止事件冒泡和事件捕获。

如果是阻止事件冒泡,只需在son的点击事件中添加event.stopPropagation()即可(这在DOM0级事件处理中同样可以);如果是阻止事件捕获,只需在father的点击事件中添加event.stopPropagation()即可。

4.事件冒泡带来的好处就是可以使用addEventListener来进行事件委托,事件委托就是指自己的事情让别人替你做。优点是:(1)比如给一个ul下的各个li都添加一个事件,不仅繁琐又耗性能,这时就可以将事件委托给ul去做。(2)比如新增dom节点,然后给新增的dom节点绑定事件,那么同样可以使用事件委托。在jQuery中,是通过                                           $("ul").delegate("li","click",function(){  console.log($(this).html());})来实现的。

下面我们来研究一下事件冒泡和事件捕获的执行顺序。W3C规定,在冒泡和捕获事件同时存在的情况下,先执行捕获。下面这个代码如果点击son这个div会弹出什么?

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #grandfather {
            width: 150px;
            height: 150px;
            background: green;
        }

        #father {
            width: 100px;
            height: 100px;
            background: red;
        }

        #son {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
    <script>
        window.onload = function () {
            let oSon = document.getElementById("son");
            let oFather = document.getElementById("father");
            let oGrandfather = document.getElementById("grandfather");
            //通过addEventListener来绑定事件,其中第三个参数是个布尔型的,false代表事件冒泡,true代表事件捕获
            oSon.addEventListener("click", function () {
                alert("son 捕获")
            }, true)
            oFather.addEventListener("click", function () {
                alert("father 冒泡")
            }, false)
            oGrandfather.addEventListener("click", function () {
                alert("grandfather 捕获")
            }, true)
        }
    </script>
</head>

<body>
    <div id="grandfather">
        <div id="father">
            <div id="son"></div>
        </div>
    </div>

</body>

</html>

答案是:依次弹出grandfather 捕获、son 捕获、father 冒泡。因为点击son后,首先会找这个son的捕获事件,就是自己和grandfather都是捕获,那么捕获是从大到下来的,故先grandfather 捕获、son 捕获,最后再去执行冒泡,也就是father 冒泡。再看一下下面这个。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #grandfather {
            width: 150px;
            height: 150px;
            background: green;
        }

        #father {
            width: 100px;
            height: 100px;
            background: red;
        }

        #son {
            width: 50px;
            height: 50px;
            background: blue;
        }
    </style>
    <script>
        window.onload = function () {
            let oSon = document.getElementById("son");
            let oFather = document.getElementById("father");
            let oGrandfather = document.getElementById("grandfather");
            //通过addEventListener来绑定事件,其中第三个参数是个布尔型的,false代表事件冒泡,true代表事件捕获
            oSon.addEventListener("click", function () {
                alert("son 冒泡")
            }, false)
            oSon.addEventListener("click", function () {
                alert("son 捕获")
            }, true)
            oFather.addEventListener("click", function () {
                alert("father 捕获")
            }, true)
            oFather.addEventListener("click", function () {
                alert("father 冒泡")
            }, false)
            oGrandfather.addEventListener("click", function () {
                alert("grandfather 捕获")
            }, true)
            oGrandfather.addEventListener("click", function () {
                alert("grandfather 冒泡")
            }, false)
        }
    </script>
</head>

<body>
    <div id="grandfather">
        <div id="father">
            <div id="son"></div>
        </div>
    </div>
</body>

</html>

就是给三个div分别添加捕获和冒泡事件,点击son这个div会弹出什么呢?答案是:grandfather 捕获、father 捕获、son 冒泡、son 捕获、father 冒泡、grandfather 冒泡。为什么?因为点击son这个div,首先响应它祖先的捕获事件,从大到小依次是grandfather 捕获、father 捕获,接下来发现son身上有两个事件,一个是冒泡,一个是捕获,那么就按代码的上下顺序来执行,即先执行son 冒泡,再执行son 捕获,最后就是father 冒泡、grandfather 冒泡。如果点击father这个div,那么弹出的是grandfather 捕获、father 捕获(因为它在冒泡的前面)、father 冒泡、grandfather 冒泡。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值