美文网首页
浏览器的事件机制-捕获与冒泡

浏览器的事件机制-捕获与冒泡

作者: Doter | 来源:发表于2020-03-18 20:40 被阅读0次

    前短时间有个面试,被问到浏览器事件机制,然后才感受到了,自己对底层知识有多差劲。

    事件流程

    先向下捕获,再向上冒泡。


    image.png

    简单来说,当你鼠标在浏览器上点击了一下。

    1. 浏览器捕获到了click事件。
    2. 然后浏览器根据你点击的事件,从window开始向下,就会触发每个父祖element捕获模式的事件回调。
    3. 直到找到点击所在的最终(最小的element)
    4. 然后浏览器开始继续又向上冒泡其父祖element的click事件,直至window。
    5. 默认的事件都是冒泡模式下触发的。

    测试

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>event test</title>
    </head>
    <body>
      <div >
        <p>
          <span>test</span>
        </p>
      </div>
     <script>
       window.addEventListener("click",clickCallback,true)
       document.body.addEventListener("click",clickCallback,true)
       document.querySelector("div").addEventListener("click",clickCallback,true)
       document.querySelector("p").addEventListener("click",clickCallback,true)
       document.querySelector("span").addEventListener("click",clickCallback,true)
       document.body.addEventListener("click",clickCallback1)
       window.addEventListener("click",clickCallback1)
       document.querySelector("div").addEventListener("click",clickCallback1)
       document.querySelector("p").addEventListener("click",clickCallback1)
       document.querySelector("span").addEventListener("click",clickCallback1)
       
       
       function clickCallback(e){
         var nodeName = e.currentTarget == window?"window":e.currentTarget.nodeName;
          console.log("捕获:",nodeName)
       }
    
       function clickCallback1(e){
        var nodeName = e.currentTarget == window?"window":e.currentTarget.nodeName;
          console.log("冒泡:",nodeName)
       }
     </script>    
    </body>
    </html>
    
    image.png

    接下来

    我们看看addEventListener第三个参数使用option,都又哪些
    可用的选项如下:

    • capture: Boolean,表示 listener 会在该类型的事件捕获阶段传播到该 EventTarget 时触发。
    • once: Boolean,表示 listener 在添加之后最多只调用一次。如果是 true, listener 会在其被调用之后自动移除。
    • passive: Boolean,设置为true时,表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。

    以上三个参数都比较好理解。

    最后再了解下

    1. 使用addEventListener为同一element设置多个clcik事件,其事件执行顺序?
      与js执行addEventListener的顺序一致,即事件注册的顺序一致。
    2. 使用addEventListener为同一element设置多个clcik事件,前面的事件执行stopPropagation,能否阻止后面事件?
      不能,只能阻止该事件(捕获)向下(冒泡)向上传播。
      3.e.preventDefault()只是阻止浏览器默认事件。

    如下demo:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>event test</title>
    </head>
    
    <body>
      <div>
        <p>
          <span>test</span>
        </p>
      </div>
      <script>
        window.addEventListener("click", clickCallback, true)
    
        document.body.addEventListener("click", clickCallback, true)
        document.body.addEventListener("click", function testEvent1(e) {
          e.stopPropagation();
          e.preventDefault();
          console.log("test1")
        }, true)
        document.body.addEventListener("click", function testEvent2() {
          console.log("test2")
        }, true)
        document.querySelector("div").addEventListener("click", clickCallback, true)
        document.querySelector("p").addEventListener("click", clickCallback, true)
        document.querySelector("span").addEventListener("click", clickCallback, true)
        document.body.addEventListener("click", clickCallback1)
        window.addEventListener("click", clickCallback1)
        document.querySelector("div").addEventListener("click", clickCallback1)
        document.querySelector("p").addEventListener("click", clickCallback1)
        document.querySelector("span").addEventListener("click", clickCallback1)
    
    
        function clickCallback(e) {
          var nodeName = e.currentTarget == window ? "window" : e.currentTarget.nodeName;
          console.log("捕获:", nodeName)
        }
        function clickCallback1(e) {
          var nodeName = e.currentTarget == window ? "window" : e.currentTarget.nodeName;
          console.log("冒泡:", nodeName)
        }
    
      </script>
    </body>
    
    </html>
    
    image.png

    在捕获期阻止事件下传递后,该事件将不会再触发冒泡事件了。

    相关文章

      网友评论

          本文标题:浏览器的事件机制-捕获与冒泡

          本文链接:https://www.haomeiwen.com/subject/ngpcyhtx.html