• JavaScript 事件机制


    事件流是一个事件沿着特定数据结构传播的过程。冒泡和捕获是事件流在DOM中两种不同的传播方法。
    事件流有三个阶段:

    1. 事件捕获阶段
    2. 处于目标阶段
    3. 事件冒泡阶段

    什么是捕获和冒泡

    假设有节点如下:

        <div id="div1">
            <div id="div2"></div>
        </div>
        
        <script>
            let div1 = document.getElementById('div1');
            let div2 = document.getElementById('div2');
            
            div1.onClick = function(){
                alert('1')
            }
            
            div2.onClick = function(){
                alert('2');
            }
        
        </script>
    
    

    当点击 div2时,会弹出两个弹出框。在 ie8/9/10、chrome浏览器,会先弹出"2"再弹出“1”,这就是事件冒泡:事件从最底层的节点向上冒泡传播。事件捕获则跟事件冒泡相反。
    W3C的标准是先捕获再冒泡addEventListener的第三个参数决定把事件注册在捕获(true)还是冒泡(false)

    事件绑定

    在各种浏览器中绑定事件有不同的写法。

    传统的事件绑定:在元素上使用 onClick绑定
    它可以适应不同的浏览器,但是只能在事件冒泡中运行(捕获不行),一次只能绑定一个。

        var ele = document.getElementById('xDiv');
        ele.onClick  =  function(e){
            console.log('指向当前的this',this);
            console.log(e.currentTarget);
        }
        
    

    w3c事件绑定:使用addEventListener()函数
    这种绑定支持冒泡捕捉,同时可以对一个元素进行多次绑定,按书写先后顺序执行。

    var ele = document.getElement('xDiv');
    
    // 最后一个参数表示事件的处理阶段,true是捕获,false是冒泡
    ele.addEventListener('click',(e)=>{
        console.log(e);
    },true);
    
    

    但是IE9以下不支持 addEventListener函数,IE浏览器要使用 attachEvent函数代替。

    IE的事件绑定attachEvent函数支持全系列IE,但是其他浏览器不支持。

        var ele = document.getElementById('xDiv');
        
        ele.attachEvent('onclick',()=>{
            console.log('指向全局的this',this);
        });
        
    

    attachEvent支持事件捕捉阶段,不支持冒泡阶段。
    另外需要注意的是 attachEvent的执行顺序是从后往前

    兼容写法
    如果我们要兼容多个浏览器的事件绑定,则可以这样写

        if(window.addEventListener){
            //chrom firefor ...
            object.addEventListener('click',function(){
            },false);
        }
        else if(window.attachEvent){
            //IE
            object.attachEvent('onclick',function(){})
        }
        else{
            object.onclick = function(){}
        }
    
    

    事件流阻止

    在一些情况下需要阻止事件流的传播,阻止默认动作的发生。

    event.preventDefault():取消事件对象的默认动作以及继续传播。
    event.stopPropagation()/ event.cancelBubble = true:阻止事件冒泡。

    事件的阻止在不同浏览器有不同处理

    • 在IE下使用 event.returnValue= false
    • 在非IE下则使用 event.preventDefault()进行阻止。

    preventDefaultstopPropagation的区别

    • preventDefault告诉浏览器不用执行与事件相关联的默认动作(如表单提交)
    • stopPropagation是停止事件继续冒泡,但是对IE9以下的浏览器无效

    事件委托

    在js中性能优化的其中一个主要思想是减少dom操作
    假设有100个li,每个li有相同的点击事件。如果为每个Li都添加事件,则会造成dom访问次数过多,引起浏览器重绘与重排的次数过多,性能则会降低。
    使用事件委托则可以解决这样的问题。

    原理

    实现事件委托是利用了事件的冒泡原理实现的。当我们为最外层的节点添加点击事件,那么里面的ul、li、a的点击事件都会冒泡到最外层节点上,委托它代为执行事件。

    实现

        <ul id="ul">
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        
        window.onload = function(){
            var ulEle = document.getElementById('ul');
            ul.onclick = function(ev){
                //兼容IE
                ev = ev || window.event;
                var target = ev.target || ev.srcElement;
                
                if(target.nodeName.toLowerCase() == 'li'){
                    alert( target.innerHTML);
                }
                
            }
        }
        


    作者:Guanmac
    链接:https://www.jianshu.com/p/916230ad9229
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    java8 快速实现List转map 、分组、过滤等操作
    Centos7系统备份与恢复
    BDI3000仿真器命令
    MIPS32地址映射和TLB
    三层交换机之报文转发流程
    三层交换机之搜索引擎
    三层交换机之端口丢包问题分析
    嵌入式Linux之虚拟内存管理
    Windows网络命令大全
    三层交换机之端口镜像(Mirror)
  • 原文地址:https://www.cnblogs.com/190luo/p/10181968.html
Copyright © 2020-2023  润新知