美文网首页让前端飞Web前端之路
JS事件冒泡、事件捕获、事件委托、事件模型

JS事件冒泡、事件捕获、事件委托、事件模型

作者: Miaoz0070 | 来源:发表于2020-04-28 18:57 被阅读0次
    JS事件

    最近跟同事一起面试,发现同时每次必问JS事件相关的内容,自己就做了下梳理,对其事件相关的内容做了下总结。

    事件模型:

    顾名思义就是事件的一个流转规则,说到事件模型就跟各个浏览器之间的差异就有关系了,目前浏览器没有统一事件模型,大致分为三种原始事件模型(DOM0级)、DOM2事件模型、IE事件模型。

    • 原始事件模型:被所有浏览器支持,原始事件没有事件流,立马触发立马响应不会传递,我自己理解就是点击只触发当前,类似阻止传递。
    //主要就是onclick事件
    (1)在html代码中直接指定属性值:<button id="demo" type="button" onclick="doSomeTing()" />
    (2)在js代码中为 document.getElementsById("demo").onclick = doSomeTing()
    

    优点:所有浏览器都兼容
    缺点:
    1.逻辑与显示没有分离;
    2.相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面的,如:a.onclick = func1; a.onclick = func2;将只会执行func2中的内容。
    3.无法通过事件的冒泡、委托等机制(后面会讲到)完成更多事情。
    因为这些缺点,虽然原始事件类型兼容所有浏览器,但仍不推荐使用,当然一般情况我们也很少使用。

    • IE事件模型:IE事件模型共有两个过程:
      事件处理阶段:事件到达目标元素, 触发目标元素的监听函数。
      事件冒泡阶段:事件从目标元素冒泡到document, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行。
      先执行元素的监听函数,然后事件沿着父节点一直冒泡到document。冒泡机制后面系列会讲,此处暂记。IE模型下的事件监听方式也挺独特,绑定监听函数的方法是:attachEvent( "eventType","handler"),其中evetType为事件的类型,如onclick,注意要加’on’。解除事件监听器的方法是 detachEvent("eventType","handler" )

    • DOM2事件模型:这种形式是W3C制定的标准模型,现代浏览器(IE6~8除外)都已经遵循这个规范。W3C制定的事件模型中,一次事件的发生包含三个过程:1.事件捕获阶段,2.事件目标阶段,3.事件冒泡阶段。下边两个图对该事件模型讲解的很清楚。


      图1
      图2

    其实我们之后要讲的事件冒泡、事件捕获、事件委托都是以此模型来讲解的。


    事件冒泡

    事件从最具体的元素到不具体的元素,从当前触发的事件目标一级一级往上传递,依次触发,直到document为止。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>xxx</title>
    </head>
    <body onclick="bodyClick()">
     <div onclick="divClick()">
       <button onclick="btn()">
          <p onclick="p()">点击冒泡</p>
       </button>
      </div>
    <script>
           
           function p(){
              console.log('p被点击')
           }
            function btn(){
                console.log("button被点击")
            }
             function divClick(event){
                 console.log('div被点击');
             }
            function bodyClick(){
                console.log('body被点击')
            }
    //也可以使用
    addEventListener('click',function(){ },false);来替换onclick。
    </script>
    </body>
    </html>
    

    p被点击》button被点击》div被点击》body被点击,即具体元素到不具体元素,从p冒泡到根节点。

    • 阻止事件冒泡:
      标准的W3C 方式:e.stopPropagation();这里的stopPropagation是标准的事件对象的一个方法,调用即可
      非标准的IE方式:ev.cancelBubble=true; 这里的cancelBubble是 IE事件对象的属性,设为true就可以了
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <div>
        <button>
            <p>点击捕获</p>
        </button>
    </div>
    <script>
        var _p=document.querySelector('p');
        var _b=document.querySelector('button');
        var _d=document.querySelector('div');
        var _body=document.querySelector('body');
       _p.addEventListener('click',function(){
            console.log('p被点击')
        },true);
    
        _b.addEventListener('click',function(){
            console.log("button被点击")
        },true);
    
        _d.addEventListener('click',  function(){
            console.log('div被点击')
        },true);
    
        _body.addEventListener('click',function(){
            console.log('body被点击')
        },true);
    
    </script>
    </body>
    </html>
    

    事件捕获

    从不具体的元素到具体的元素,从document开始触发,一级一级往下传递,依次触发,直到真正事件目标为止。

    body被点击》div被点击》buton被点击》p被点击,即跟冒泡是相反的,从不具体元素到具体元素,从根节点到p标签。


    事件委托
    • 原理:事件冒泡机制
      利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。借网上别人的例子简单明了的解释:
      有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
    • 优点:
      1.大量减少内存占用,减少事件注册。
      2.新增元素实现动态绑定事件
    <ul id="ul">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
    
    • 实现方式:
      1.可用addEventListener(); //所有主流浏览器,除了IE8及更早IE版本。
    ul.addEventListener("click",function(e) { 
    
       if(e.target && e.target.nodeName.toLowerCase() == "li") {  // 检查事件源e.target是否为li
         console.log("List item ",e.target.id.replace("post-","")," was clicked!");  // 打印当前点击是第几个item 
        } 
    });
    

    2.attachEvent() //IE8及IE更早版本,现在已经不怎么使用。
    <1>.用法:element.attachEvent(event,function);
    (1)event事件加'on',onClick
    (2)没有第三个参数,因为IE只有冒泡,没有反向冒泡。
    (3)执行顺序按照绑定的反序(先执行后绑定的方法)。
    <2>.移除事件监听:element.detachEvent(event,function)

    以上就是JS事件冒泡、捕获、委托和事件模型的相关个人理解,有错误之处还请指正。

    相关文章

      网友评论

        本文标题:JS事件冒泡、事件捕获、事件委托、事件模型

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