• JS 事件


    事件

    事件是 JS 和 HTML 交互的桥梁。采用“观察者模式”,使用仅在事件发生时执行的监听器(也叫处理程序)订阅事件

    事件流

    事件流描述的是页面接收事件的顺序。分为 3 各阶段:

    • 事件捕获:最先触发,可以做事件拦截。
    • 到达事件目标:触发目标事件
    • 事件冒泡:可以拦截事件响应

    如下代码的事件流为

    <body>
      <div id="test" onclick="console.log(event)"></div>
    </body>
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    事件处理程序

    事件处理程序(或事件监听器):为响应事件而调用的函数,以"on"开头。

    函数体在 HTML 中

    如果事件处理程序很简单,那么可以直接写在 HTML 中,但是要注意不能在未经转义的情况下使用 HTML 语法字符,例如和号(&)、双引号(")、小于号(<)和大于号(>)。

    <div onclick="console.log('Clicked')"></div>
    
    • 1

    函数有一个特殊的局部变量 event (事件对象),它保存有事件的一些关键信息,后边会重点介绍。以这种方式定义的事件处理程序中的 this 指向事件的目标元素,并且可以更方便地访问自己的属性。

    <div onclick="console.log(event)"></div>
    <div onclick="console.log(this)"></div>
    <div id="test" onclick="console.log(id)"></div>
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    以这种方式添加事件处理程序会导致 HTML 和 JS 的强耦合,不利于后期维护。

    DOM 绑定事件

    如下这样的方式为事件处理程序赋值时,事件处理程序会在元素的作用域中运行,所以 this 指向目标元素本身。这种方式添加事件处理程序是注册在事件流的冒泡阶段触发。

    直接赋值
    <div id="test"></div>
    <script>
      let oDiv = document.getElementById('test');
      oDiv.onclick = function (event) {
        console.log(event, this)
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    移除事件处理程序只需要将处理程序属性值设为 null

    <div id="test"></div>
    <script>
      let oDiv = document.getElementById('test');
      oDiv.onclick = function (event) {
        console.log(event, this)
      }
      // 移除事件处理程序
      oDiv.onclick = null;
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    addEventListener & removeEventListener

    addEventListener 接收 3 个参数:

    • 事件名
    • 事件处理函数
    • 一个布尔值,true 表示在捕获阶段调用事件处理程序,false(默认值)表示在冒泡阶段调用事件处理程序。

    使用 addEventListener 可以为同一个事件添加多个事件处理程序,以添加顺序来触发。

    <div id="test"></div>
    <script>
      let oDiv = document.getElementById('test');
      oDiv.addEventListener('click', function (event) { console.log(event, this) }, true)
      oDiv.addEventListener('click', function () { console.log(this) }, true)
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    通过 addEventListener 添加的事件处理程序只能使用 removeEventListener 来移除。接收三个参数:

    • 事件名
    • 添加事件时的事件处理程序
    • 同添加事件时一样
    <div id="test"></div>
    <script>
      let oDiv = document.getElementById('test');
      function click(event) {
        console.log(event)
      }
      oDiv.addEventListener('click', click, true);
      oDiv.removeEventListener('click', click, true);
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意:不要使用 addEventListener 方法添加匿名的事件处理程序,因为这样无法移除。

    事件对象

    DOM 事件触发时,所有相关信息都会被收集并存储在 event 的对象中。事件对象包含事件相关的属性和方法。不同的事件生成的事件对象也会不同。

    注意 event 对象只在事件处理程序执行期间存在,一旦执行完毕,就会被销毁。
    在这里插入图片描述
    每个事件对象都包含 currentTarget 和 target 属性。currentTarget 属性是事件绑定的元素,target 是事件的真正目标。这两个属性比较重要。

    下面的例子,事件绑定在 body 身上,但是我点击的是 div,所以 currentTarget 为 body 元素对象,target 为 div 元素对象。

    <div id="test"></div>
    <script>
      function click(event) {
        console.log(event.currentTarget, event.target);
      }
      document.body.addEventListener('click', click);
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    preventDefault 方法用于阻止特定事件的默认行为。比如 a 标签的默认行为是点击打开 href 链接,但是如果添加如下方法就能阻止打开链接。

    let oA = document.getElementById("myLink"); 
    oA.onclick = function(event) { 
     event.preventDefault(); 
    };
    
    • 1
    • 2
    • 3
    • 4

    stopPropagation 方法用于取消后续的事件捕获或冒泡。如下例子,在 div 绑定的事件中调用了stopPropagation ,那么就不会再继续冒泡了,body 的点击事件自然不会触发。

    <div id="test"></div>
    <script>
      let oDiv = document.getElementById('test');
      oDiv.onclick = function (event) {
        console.log("div Clicked");
        event.stopPropagation();
      }
      document.body.onclick = function (event) {
        console.log("Body clicked");
      };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    事件委托

    设想一种情况,当有一个 ul 标签,其内有许多 li 标签,我需要在点击 li 标签是能够做一些处理,最简单的方法就是给每一个 li 标签都绑定一个点击事件,但是这就带来一个问题,由于每个函数都是一个对象,那么对象越多占用内存就越多,性能就越差。为了解决这种情况就提出了事件委托。

    事件委托就是把子元素的事件处理程序绑定在父元素上,利用事件冒泡来触发事件。如下例:

    <div id="test">
        <div id="1"></div>
        <div id="2"></div>
        <div id="3"></div>
    </div>
    <script>
        let oDiv = document.getElementById('test');
        oDiv.onclick = function (event) {
          let target = event.target;
          switch (target.id) {
            case "1":
              console.log(target.id + 1);
              break;
            case "2":
              console.log(target.id + 2);
              break;
            case "3":
              console.log(target.id + 3);
              break;
          }
        }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    我是孤城浪人,一名正在前端路上摸爬滚打的菜鸟,欢迎你的关注。

  • 相关阅读:
    MR直播(混合现实直播)做一场高品质企业培训
    代码随想录——字符串篇
    QTableView右键显示菜单
    Matlab中的handle 类
    什么是原生IP?原生IP与住宅IP有何区别?
    大数据技术Flink详解
    计算机网络 ,什么是Internet?什么是协议?TCP/UDP的区别以及优缺点 分组交换与电路交换的区别以及优缺点
    Elasticsearch - What‘s new in 8.3
    计算机基础 码制与位运算
    基础课-排列组合
  • 原文地址:https://blog.csdn.net/weixin_46015333/article/details/127947835