• 事件及事件流


    事件与事件流

    用户在点击网页上某一按钮时,浏览器会想办法接收这一操作,如何接收呢? 浏览器会为点击操作划定若干个范围,从小到大依次是按钮本身,包含这个按钮的元素, 最后就是整个页面。这一操作称为事件,而接收事件的次序称为事件流。 事件流总共有两种形式:事件冒泡事件捕获

    事件冒泡

    事件冒泡就是从小到大,从具体对象到不具体对象,像泡泡一样逐级向上

    <html></html>
    <body>
        <div id="div1">
            <div id="div2">
                <button>click me!</button>
            </div>
        </div>
    </body>

    当用户打开上述代码编写的页面,点击按钮时,如果浏览器采取的是事件冒泡的事件接收机制, 那么浏览器就先从button元素开始接收,然后是然后是div2,然后是div1,最终到document对象(规范是到document为止, 但是大多数浏览器都会一直冒泡到window对象),如图所示。

    事件捕获

    事件捕获就是事件冒泡的反序。从大到小,从不具体对象到具体对象,逐级向下。

    如果浏览器采取的是事件捕获的事件接收机制, 浏览器先从document对象(规范定的是document对象,大多数浏览器是从window对象处开始接收)开始接收, 然后是<html>元素,然后是<body>元素,最后在<button>元素处接收。

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8" />
            <meta http-equiv="contentType" content="text/html" />
            <title>Test</title>
        </head>
        <body>
            <div id="div1">
                <div id="div2">
                    <button>click me!</button>
                </div>
            </div>
            <script src="scripts/test.js" type="text/javascript"></script>
        </body>
    </html>
    var div1 = document.querySelector("#div1");
    var div2 = document.querySelector("#div2");
    var button = document.querySelector("button");
    
    div1.addEventListener("click",function(event){
        console.log("div1");
    },false); //传入false,事件冒泡
    div2.addEventListener("click",function(event){
        console.log("div2");
    },false);
    button.addEventListener("click",function(event){
        console.log("button");
    },false);

    上述代码使用addEventListener()方法,分别为div1,div2,button元素添加了事件处理程序, 并显示的指定事件流为事件冒泡机制,浏览器按具体对象到不具体对象的顺序接收事件。所以控制台输出

    同一段代码,但显示的指定事件流为事件捕获机制,浏览器按不具体对象到具体对象的顺序接收事件, 控制台输出。

    有什么用

    理解事件流的这两种机制有什么用?其实这对理解某些DOM事件是很有好处的,比如mouseover、mouseout、mouseleave、mouseenter。 其中,mouseover和mouseout是一对儿,鼠标进入目标元素时接收mouseover,离开目标元素时接收mouseout事件。 mouseenter和mouseleave是一对儿,鼠标进入目标元素时接收mouseenter,离开目标元素时接收mouseleave事件, 但是他俩不冒泡!所以鼠标进入、离开其后代元素时,其父元素无法接受到mouseenter和mouseleave事件。

    <div id="target">
                <p>
                    Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/>
                    Lorem Ipsum has been the industry's standard dummy text ever since the 1500.
                </p>
                <p>
                    Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/>
                    Lorem Ipsum has been the industry's standard dummy text ever since the 1500.
                </p>
                <p>
                    Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/>
                    Lorem Ipsum has been the industry's standard dummy text ever since the 1500.
                </p>
                <p>
                    Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/>
                    Lorem Ipsum has been the industry's standard dummy text ever since the 1500.
                </p>
            </div>
    var target = document.querySelector("#target");
    /**
     * 使用mouseenter和mouseleave事件,进入target时浏览器接受mouseenter事件,
     * 离开target时浏览器接受mouseleave事件。
     * 在target中移动鼠标(在各个<p>元素之间切换),因为不冒泡,所以target不会继续接收到mouseenter和mouseleave,
     * 也就不会调用相应的事件处理程序
     */
    target.addEventListener("mouseenter",function(event) {
        console.log("parent mouseenter");
    },false);
    target.addEventListener("mouseleave",function(event) {
        console.log("parent mouseleave");
    },false);
    /**
     * 使用mouseout和mouseover事件, 在target中移动鼠标(在各个<p>元素之间切换),由于事件流是事件冒泡机制,
     * 所以target就会接收到其子元素冒泡而来的mouseenter和mouseleave,从而调用相应的事件处理机制
     */
    target.addEventListener("mouseout",function(event) {
        console.log("parent mouseout");
    },false);
    target.addEventListener("mouseover",function(event) {
        console.log("parent mouseover");
    },false);

    如控制带输出所示,鼠标横穿target,mouseenter仅触发了一次,mouseleave也仅触发了一次。而mouseout、mouseover触发了若干次。

    总结

    事件:用户的某一操作

    事件流:浏览器接受事件的顺序

    事件冒泡:从具体对象到不具体对象,逐级向上接收

    事件捕获:从不具体对象到具体对象,逐级向下接收

     参考资料

    1.《javascript高级程序设计》

  • 相关阅读:
    观察者模式
    字符串操作函数
    位域结构体的字节对齐
    备忘任务
    Linux编程下EAGAIN和EINTR宏的含义及处理
    Linux 中write()函数的出错情况及处理
    Nginx配置配置文件nginx.conf的设置
    Linux编程获取本地IP
    redis与memcached比较
    TCP通讯socket自定义协议的实现
  • 原文地址:https://www.cnblogs.com/fudashi/p/6291275.html
Copyright © 2020-2023  润新知