美文网首页
DOM事件详解

DOM事件详解

作者: amanohina | 来源:发表于2020-12-13 10:09 被阅读0次

    绑定事件方法

    注册事件的其他方法1

    • element.addEventListener()方法
    • 参数:
      1.事件类型的字符串(直接书写”click”,不需要加 on)
      2.事件函数
    • 同一个元素可以多次绑定事件监听,同一个事件类型可以注册多个事件函数
    • 兼容性问题:不支持 IE9 以下的浏览器
      我们把这个绑定方法称之为DOM2级事件绑定
      btn.addEventListener("click",function(){
          alert("1");
        });
    // 多次绑定相同的事件类型,事件会根据书写的顺序进行事件的排队
        btn.addEventListener("click",clickEvent);
        function clickEvent() {
          alert("2");
        }
    

    注册事件的其他方法2

    • element.attachEvent() 方法
    • 参数
      1.事件类型的字符串(需要加on)
      2.事件函数
    • 同一个元素可以多次绑定事件监听,同一个事件类型可以注册多个事件函数
    • 兼容性问题:只支持IE10及以下的浏览器


      在IE10及以下浏览器之外的运行结果
    var btn = document.getElementById("btn");    
        // DOM 2 级事件绑定方式
        // 兼容:IE 10 及以下浏览器
        // IE8 及以下的浏览器处理事件队列时,会出现顺序错乱
        btn.attachEvent("onclick",function () {
          alert(3);
        });
        btn.attachEvent("onclick",clickEvent);
        function clickEvent() {
          alert(4);
        }
    

    IE8及以下浏览器处理事件队列的时候会出现顺序错乱

    注册事件兼容写法

    • 自定义一个注册事件函数
    • 参数:事件源,事件类型(不加on)。事件函数
    • IE9及以上的浏览器,使用addEventListener方法
    • IE9以下的浏览器,使用attachEvent方法
    • 判断浏览器时,不需要判断它的版本,可以检测浏览器能力
    • 浏览器能力监测:将某个方法的调用作为if语句的判断条件,如果浏览器认识该方法返回true,否则false
      比如:
      <script>
        var btn = document.getElementById("btn");
        // DOM 2 级事件绑定方式
        // 调用函数
        addEvent(btn,"click",function(){
          alert("1")
        });
        // 自己制作一个兼容所有浏览器的绑定事件的函数
        // 参数:事件源,事件类型,事件函数
        function addEvent(ele,type,fn){
          // 判断,IE 9 及以上和其他浏览器,使用addEVentListener
          // IE 9 及以下的浏览器,使用attachEvent
          // 浏览器能力监测
          if(ele.addEventListener){
            ele.addEventListener(type,fn);
          }else if(ele.attachEvent){
            ele.attachEvent("on"+type,fn);
          }
        }
        </script>
    

    移除事件

    移除事件的其他方法1

    • element.removeEventListener()方法
    • 参数
      1.事件类型的字符串(直接书写"click",不需要加on)
      2.事件函数引用名
    • 注意:没有办法移除一个匿名函数,所以在注册事件时需要单独声明
    • 兼容性问题:不支持IE 9 以下的浏览器

    移除绑定的语句必须要在绑定事件语句之后进行

    <script>
        var btn = document.getElementById("btn");
        // 绑定事件
        // btn.onclick = function(){
        //   alert(1);
        // };
        // // 解除绑定方法:
        // btn.onclick = null;
    
        // 绑定事件
        btn.addEventListener("click",fun);
        btn.addEventListener("click",fun2);
        function fun2(){
          alert(2);
        }
        function fun(){
          alert(1);
        }
        // 解除绑定
        btn.removeEventListener("click",fun);
        btn.removeEventListener("click",fun2);
        </script>
    

    移除事件的其他方法2

    • element.detachEvent() 方法。
    • 参数:第一个参数:事件类型的字符串(需要加 on) 第二个参数:事件函数
    • 注意:没有办法移除一个匿名函数,所以在注册事件时需要单独声明一个有函数名的事件函数。
    • 兼容性问题:只支持 IE10 及以下的浏览器
    // 绑定事件
        btn.attachEvent("onclick",fun);
        btn.attachEvent("onclick",fun2);
        // btn.detachEvent("onclick",fun);
        function fun(){
          alert(2);
        }
        function fun2(){
          alert(3);
        }
    

    解除事件兼容写法

    • 自定义一个移除事件函数
    • 参数:事件源,事件类型(不加 on),事件函数
    • IE9 及以上的浏览器,使用 removeEventListener 方法
    • IE9 以下的浏览器,使用 detachEvent 方法
    • 建议:将自己封装的一些常用函数和方法,放到一个单独的 .js 文件中。
    // 兼容所在浏览器的解除绑定事件的函数
        // 参数:事件源,事件类型,事件函数
        function removeEvent(ele,type,fn){
          // 浏览器能力监测
          if(ele.removeEventListener){
            ele.removeEventListener(type,fn);
          }else if(ele.detachEvent){
            ele.detachEvent("on"+type,fn);
          }
        }
    

    将绑定和解除事件兼容的写法封装到js库内,如下:(获取id,绑定事件,解除事件)

    // 定义一个获取元素的函数
    function my$(id) {
      return document.getElementById(id);
    }
    
    // DOM 2 级事件绑定方式
    // 自己制作一个兼容所有浏览器的绑定事件的函数
    // 参数:事件源,事件类型,事件函数
    function addEvent(ele, type, fn) {
      // IE 9 及以上的浏览器和其他浏览器,使用 addEventListener 方法
      // IE 9 以下的浏览器,使用 attachEvent 方法
      // 浏览器能力检测
      if (ele.addEventListener) {
        ele.addEventListener(type, fn);
      } else if (ele.attachEvent) {
        ele.attachEvent("on" + type, fn);
      }
    }
    
    // 兼容所有浏览器的 解除绑定事件的函数
    // 参数:事件源,事件类型,事件函数
    function removeEvent(ele, type, fn) {
      // 浏览器能力检测
      if (ele.removeEventListener) {
        ele.removeEventListener(type, fn);
      } else if (ele.detachEvent) {
        ele.detachEvent("on" + type, fn);
      }
    }
    

    DOM事件流

    事件流,先捕获,再冒泡
    <script>
            var box1 = document.getElementById("box1");
            var box2 = document.getElementById("box2");
            var box3 = document.getElementById("box3");
    
            // 添加点击事件
            // addEventListener有第三个参数,用来决定事件流的方向
            // 参数值是布尔值,false表示事件流是按照事件冒泡的过程执行的,true表示事件捕获过程
            // 参数的默认值是false,默认为时间冒泡过程
            box1.addEventListener("click",function(){
                console.log(this.id);
            });
            box2.addEventListener("click",function(){
                console.log(this.id);
            });
            box3.addEventListener("click",function(){
                console.log(this.id);
            });
    
            box1.addEventListener("click",function(){
                console.log(this.id);
            },true);
            box2.addEventListener("click",function(){
                console.log(this.id);
            },true);
            box3.addEventListener("click",function(){
                console.log(this.id);
            },true);
    
            // 冒泡过程和捕获过程一起执行是先进行捕获,再进行冒泡
        </script>
    
    显而易见,先捕获,再冒泡

    事件流的三个阶段

    • 第一个阶段:事件捕获
    • 第二个阶段:事件执行过程
    • 第三个阶段:事件冒泡
    • addEventListener()第三个参数为false,事件冒泡
    • addEventListener()第三个参数为true,事件捕获
    • onclick类型:只能进行事件冒泡过程,没有捕获阶段
    • attachEvent()方法:只能进行事件冒泡过程,没有捕获阶段

    事件冒泡的应用——事件委托

    • 利用事件冒泡,将子级的事件委托给父级加载
    • 同时,需要利用事件函数的一个参数e,内部存储的是事件对象
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            ul {
                width: 300px;
                border: 1px dashed #f0f;
                margin: 50px auto;
                font-size: 24px;
                line-height: 48px;
                list-style: none;
            }
            li {
                padding-left: 20px;
                cursor: pointer;
            }
    
        </style>
    </head>
    
    <body>
        <ul id="list">
            <li>刘亦菲</li>
            <li>杨幂</li>
            <li>唐嫣</li>
            <li>赵丽颖</li>
            <li>刘诗诗</li>
        </ul>
        <script>
            // 让每个 li 被点击后,自己添加特殊的背景色,而其他兄弟不添加
            // 以前的思路,获取所有的li标签元素,然后批量添加事件
            // 事件委托原理:可以将一些子级的公共类型的事件委托给父级添加,然后在父级内部想办法找到真正触发事件的最底层的事件源
            // 获取元素
            var list = document.getElementById("list");
            var lis = list.children;
            // 事件委托的过程,给ul添加点击事件
            list.onclick = function(e){
                // 内部要想办法找到真正触发事件的li
                // 借用事件函数内部的一个参数,e是事件对象
                // 只要触发了事件,这时候函数内部他都可以得到一个事件对象,对象中存储了关于事件的一系列数据
                // e.target 这个属性记录的就是真正触发的事件的事件源
                // 排除其他
                for(var i = 0;i<lis.length;i++){
                    lis[i].style.backgroundColor = "";
                }
                e.target.style.backgroundColor = "pink";
            };
        </script>
    </body>
    
    </html>
    

    事件对象

    • 只要触发了事件,就会有一个对象,内部存储了与事件相关的数据
    • e 在低版本浏览器有兼容问题,低版本浏览器用的是window.event
    • 事件对象常用的属性:
      e.eventPhase ——查看事件触发时所处的阶段
      1:捕获阶段
      2:目标执行阶段
      3:冒泡阶段
      e.target ——用于获取触发事件的元素
      e.srcElement ——用于获取触发事件的元素,低版本浏览器使用
      e.currentTarget——用于获取绑定事件的事件源(事件绑定的事件源是谁)
     box1.onclick = function (e) {
    // 获取绑定事件的事件源元素
                console.log(e.currentTarget);
    }
    

    box1就是事件源

    也可以用this代替指向

    e.type——获取事件类型

    // 可以将所有给一个元素绑定的事件的事件函数写在一个函数内,通过函数内部的e.type判断走不同的分支
        // 避免添加多个函数,占用更多的内存
        
        box1.onmouseover = fn;
        box1.onmouseout = fn;
    
        function fn(e){
            e = e || window.event;
            // 根据事件类型执行不同的代码
            switch(e.type){
                case "mouseover":
                    box1.style.backgroundColor = "skyblue";
                    break;
                case "mouseout":
                    box1.style.backgroundColor = "yellowgreen";
                    break;
            }
        }
    

    e.clientX/e.cilentY——所有浏览器都支持,鼠标距离浏览器窗口左上角的距离
    e.pageX/e.pageY——IE8以前不支持,鼠标距离整个HTML页面左上顶点的距离

    // 事件对象中有一些获取尺寸的属性
            box1.onclick = function(e){
                // client系列:客户端尺寸,点击的点参考浏览器窗口左上角的距离,跟自己页面的左上角没有关系
                console.log(e.clientX);
                console.log(e.clientY);
                // page系列,html页面尺寸,点击的点参考HTML文档左上角的距离
                console.log(e.pageX);
                console.log(e.pageY);
    

    事件对象案例:图片跟随鼠标移动而移动

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
          * {
            margin: 0;
            padding: 0;
          }
          #pic {
            position: fixed;
          }
        </style>
    </head>
    <body>
        <img src="images/tianshi.gif" alt="" id="pic">
        <script>
          //  通过鼠标移动事件给图片添加left和top值
          // 获取元素
          var pic = document.getElementById("pic");
          // 添加鼠标移动事件(给整个文档)
          document.onmousemove = function(e){
            e = e || window.event;
            // 给pic元素css属性赋值
            pic.style.left = e.clientX + "px";
            pic.style.top = e.clientY + "px";
          };
        </script>
    </body>
    </html>
    

    取消默认行为和阻止冒泡(阻止事件传播)

    • e.preventDefault() 取消默认行为 ,低版本浏览器不能兼容
    • e.returnValue 取消默认行为,低版本浏览器使用
    <body>
      <a id="link" href="52_图片跟随鼠标移动效果.html">点击</a>
      <script>
        var link = document.getElementById('link');
        link.onclick = function (e) {
          e = e || window.event;
          alert('hello');
          // 普通的方式阻止默认行为
          // return false;
          // DOM 的方法
          // e.preventDefault();
          // 低版本浏览器需要使用一个对象的属性
          e.returnValue = false;
        }
      </script>
    </body>
    
    • e.stopPropagation(); 阻止冒泡,标准方式
    • e.cancelBubble = true; 阻止冒泡,IE 低版本,标准中已废弃
    <script>
        // 事件冒泡
        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var box3 = document.getElementById('box3');
    
        var array = [box1, box2, box3];
    
        for (var i = 0; i < array.length; i++) {
          var box = array[i];
          box.onclick = function (e) {
            e = e || window.event;
            console.log(this.id);
            // 阻止事件冒泡
            // e.stopPropagation();
            // 低版本浏览器使用 属性
            e.cancelBubble = true;
          }
        }
      </script> 
    

    其他常见事件类型

    参考资料:

    https://developer.mozilla.org/zh-CN/docs/Web/Events

    相关文章

      网友评论

          本文标题:DOM事件详解

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