• Js-事件分发与DOM事件流


    原文地址:https://www.jianshu.com/p/dc1520327022

    Js事件分发与DOM事件流

    对JavaScript分发事件不熟悉,网上查阅相关资料整理后,记录一下对Javascript事件分发机制相关的知识。
    当触发某个事件时会相应生成一个事件对象,而这个事件对象则会根据DOM事件流的方向进传递,看下图:

    图为通过DOM事件流在DOM树传递事件的示意
    图为通过DOM事件流在DOM树传递事件的示意

    图片来源:http://www.w3.org/TR/DOM-Level-3-Events/#event-flow
    事件对象会随着DOM事件流从Window依次向下,最终传递给事件目标。但是在这个过程开始之前,事件对象的传递路径需要先被确定下来。
    这个传递路径是一个有序的列表,里面包含了传递到事件目标需要经过的节点。而传递路径反映了文档的树结构。列表里面的最后一项就是事件目标,列表里面先于它的项指向目标的祖先节点,它的上一项指向目标的父节点。
    比如上图由Window->Document->html->body->table->tr->td。一旦传递路径被确定了,事件对象就可以经历一个或者多个事件阶段。通常有三个阶段:捕获阶段目标阶段冒泡阶段。某些阶段可能会被跳过,如果浏览器不支持,或者事件对象的传播被停止了。例如,如果把cancelBubble设置为true,冒泡阶段将会被跳过,或者stopPropagation()方法在传递之前就被调用的话,之后所有的阶段都会被跳过。
    • 捕获阶段:事件对象从目标的祖先节点Window开始传播直至目标。
    • 目标阶段:事件对象传递到事件目标。如果事件的type属性表明后面不会进行冒泡操作,那么事件到此就结束了。
    • 冒泡阶段:事件对象以一个相反的方向进行传递,从目标开始,到Window对象结束。
      直接上代码,写了三个嵌套的div:
    <!DOCTYPE >
    <html>
    <head lang="en">
        <title></title>
        <meta charset="UTF-8">
        <style type="text/css">
            #parent { width: 300px; height: 300px;padding:10px;background:lightyellow;}
            #child { width: 200px; height: 200px; background: lightblue; }
            #grandchild { width: 100px; height: 100px; background: lightcoral; }
        </style>
    </head>
    <body>
    <div id="parent">
        parent
        <div id="child">
            child
            <div id="grandchild">
                grandchild
            </div>
        </div>
    </div>
    
    <script type="text/javascript">
        window.alert = function (msg) {
            console.log(msg);
        };
        var parent= document.getElementById('parent'),
            child = document.getElementById('child'),
            grandchild = document.getElementById('grandchild');
    
        parent.addEventListener('click', function (e) {
            alert('父节点冒泡')
        }, false);
        parent.addEventListener('click', function (e) {
            alert('父节点捕获')
        }, true);
        child.addEventListener('click', function (e) {
            alert('子节点捕获')
        }, true);
        child.addEventListener('click', function (e) {
            alert('子节点冒泡')
        }, false);
        grandchild.addEventListener('click', function (e) {
            alert('孙子节点冒泡')
        }, false);
        grandchild.addEventListener('click', function (e) {
            alert('孙子节点捕获')
        }, true);
    
    </script>
    </body>
    </html>

    当点击了parent时,依次打印:父节点冒泡,父节点捕获。
    当点击了child时,依次打印:父节点捕获,子节点捕获,子节点冒泡,父节点冒泡。
    当点击了grandchild时,依次打印:父节点捕获,子节点捕获,孙子节点冒泡,孙子节点捕获,子节点冒泡,父节点冒泡。
    由此可以得出来结论,点击了目标节点后,捕获阶段里事件会从外向目标传递;到了目标阶段,捕获和冒泡的执行顺序按照事件被定义的先后顺序执行;最后冒泡阶段,又会由目标向外进行传递。

    补充说明事件中stopPropagationstopImmediatePropagation区别:
    两都都可以阻止事件的进一步捕获或冒泡,但后者同时可以阻止任何事件处理程序被调用,包括目标阶段的事件。
    比如修改上面代码里面子节点的目标事件:

       child.addEventListener('click', function (e) {
            alert('子节点捕获')
        }, true);
        child.addEventListener('click', function (e) {
            e.stopPropagation();
            // e.stopImmediatePropagation();
            alert('子节点捕获2')
        }, true);
        child.addEventListener('click', function (e) {
            alert('子节点冒泡')
        }, false);

    使用stopPropagation():点击子节点,依次打印:父节点捕获,子节点捕获,子节点捕获2,子节点冒泡。
    使用stopImmediatePropagation():点击子节点,依次打印:父节点捕获,子节点捕获,子节点捕获2。
    两者都阻止了事件向父节点进行传播,同时使用stopImmediatePropagation()阻止了事件向目标阶段后面的事件的传播。
    参考:
    https://www.w3.org/TR/DOM-Level-3-Events/#event-flow

    如果您在阅读过程中发现有什么问题,欢迎指正。

  • 相关阅读:
    python基础知识(集合)
    python基础知识(字典)
    python基础知识(循环语句)
    Python基础知识(程序结构)
    python基础知识(正则表达式)
    python基础知识(字符串)
    jmeer_09_JDBC Request
    性能总结_01
    性能02_
    jmeter_07正则提取器_JDBC_Connection_Configuration
  • 原文地址:https://www.cnblogs.com/boonya/p/11165167.html
Copyright © 2020-2023  润新知