• JS学习笔记——事件


    1.事件流

    当我们点击网页上的某一个元素时,触发的动作不仅仅跟这个元素有关,还跟包含这个元素的所有上层容器有关。触发事件流的流动有一个先后顺序,目前有两种:1.IE所提出的事件冒泡;2.Netscape所提出的事件捕获。
    DOM事件流则是综合了前面两种事件流,先捕获再冒泡。现代浏览器大多支持DOM事件流。



    2.事件处理程序

    为元素绑定相应的事件处理程序有3种方法:HTML、DOM0级、DOM2级。事件处理程序以”on”开头,如”click”事件的处理程序是”onclick()”。

    2.1 HTML事件处理

    我们把事件处理程序当做html的元素属性加入html标签中。这种方法的最大缺点就是html和js紧耦合。

    <input type="button" value="button" onclick="alert(`Click Me`)" />
    <input type="button" value="button" onclick="test()" />
    
    <script>
    function test() {
        //...
    }
    </script>

    2.2 DOM0级事件处理

    通过DOM操作获取元素,元素都带有事件处理(比如onclik())的属性,我们把函数赋值给该属性即可。在事件处理程序中,this指向给调用该事件处理程序的元素(在事件委托中,this就指向那个尽量高层次的元素)。若想删除事件处理程序,将该属性赋值null即可。DOM0级绑定的事件处理程序会发生在冒泡阶段。

    var p = document.getElementById('p');
    p.onclick = function() {
        alert(this.id);//p
    }
    p.onclick = null;//删除绑定的事件处理程序

    2.3 DOM2级事件处理

    DOM2级事件处理程序的功能比DOM0级更加丰富。DOM2级可以一个事件添加多个处理程序,还可以指定程序在冒泡阶段调用还是捕获阶段调用。DOM2级要删除处理程序,需要传入添加函数时的那个函数参数,这就说明,添加的匿名函数无法删除。

    var p = document.getElementById('p');
    p.addEventListener("click", function(){
        alert(this.id);//p
    }, false);//第三个参数 true:捕获阶段调用;false:冒泡阶段调用;
    
    //该移除函数没有起作用
    p.removeEventListener("click", function(){
        alert(this.id);
    }, false);

    2.4 IE事件处理

    虽然IE9也支持DOM2级事件处理程序(DOM事件流),但在IE9以前,是只支持IE事件处理(IE事件流)的。IE事件流是事件冒泡。IE事件处理程序与DOM2级事件处理程序非常相似。IE事件处理只支持两个参数,第三个参数无法选择捕获还是冒泡。在IE8以及更早版本中,只支持冒泡。与DOM2级不同的是,这里的this指向全局window。
    这里我们注意,并不是所有IE浏览器都是IE事件处理(IE事件流),像IE9就支持DOM事件流,支持DOM事件流,也支持DOM2级事件处理程序。

    var p = document.getElementById('p');
    
    p.attachEvent("onclick", function(){//注意这里是"onclick",而不是DOM2级的"click"
        alert(this === window);//true
    });
    
    //与DOM2级一样,匿名函数无法被删除
    p.detachEvent("onclick", function(){
        alert(this === window);//true
    });

    3.DOM事件对象

    事件对象分为DOM事件对象和IE事件对象,IE就是个奇葩的存在,除了IE之外,其他浏览器都是DOM事件对象。
    事件处理程序会接收一个事件对象,该事件对象中有许多跟事件有关的属性,比如type、churentTarget、target等。
    下面我们区分一下三个容易混淆的属性thistargetcurrentTarget。this始终等于currentTarget,这两个又等于调用处理程序的元素。target等于动作真实发生的对象。

    <body>
        <div id='div'>
            <p id='p'>hello!</p>
        </div>
    </body>
    
    //div是p的父元素,如果点击p,event.target就是p
    //如果点击div其他地方(不是p),event.target就是div
    div.detachEvent("onclick", function(event){
        //event.type == "click"
        alert(this === div);//true
        alert(event.currentTarget === div);//true
        alert(event.target === p);//true
    });

    4.事件代理(事件委托)

    如果我们有许多的元素需要绑定事件处理程序,按照上面的方法:先使用DOM获取元素,再给元素绑定函数。这种方法会使得web性能下降:DOM操作耗时;函数的本质是对象,耗内存。
    这种场景的解决方法就是使用事件代理,即利用事件冒泡,给尽量高层次的元素绑定一个事件,在这个事件中,根据事件对象的属性来做相应的处理。

    div.onclick = function(event) {
        switch(event.target.id) {
            case 'p':
                alert('p');
                break;
            case 'div':
                alert('div');
                break;
        }
    }
  • 相关阅读:
    Docker-CentOS系统安装Docker
    Docker-准备Docker环境
    Docker系列-文章汇总
    商品订单库存一致性问题的思考
    java模板、工厂设计模式在项目中的重构
    2018Java年底总结
    java的AQS中enp没有同步代码块为啥是原子操作
    java使用awt包在生产环境docker部署时出现中文乱码的处理
    初探装饰器模式
    开灯问题
  • 原文地址:https://www.cnblogs.com/season-peng/p/6759508.html
Copyright © 2020-2023  润新知