DOM - 事件注册

dom0 时代

dom0 注册事件

  1. 在 dom0 的时候将事件名称前面加上 on,作为 dom 属性名,给该属性赋值为一个函数
    ,即为事件注册,如下:

    <button class="btn1">点击1</button>
    
    <script>
      const btn1 = document.querySelector('.btn1')
      btn1.onclick = function () {
        console.log('被点击了')
      }
    </script>
    
  2. 当然还可以直接在标签上注册事件,如下:

    <!-- 也可以直接在标签上使用 -->
    <!-- onclick 双引号内部就可以直接运行 js 代码 -->
    <!-- 这种情况下,默认就是一个函数环境,不用自己额外编写函数 -->
    <button class="btn2" onclick="alert('btn2被点击')">点击二</button>
    
  3. 也可以是一个函数,如下:

    <button class="btn3" onclick="foo()">调用函数</button>
    
    <script>
      function foo() {
        console.log('foo 函数被调用了');
      }
    </script>
    
  4. 但是不是很推荐在 html 元素中直接绑定事件,这样的代码后期难以维护,且容易发生错误

dom0 移除事件

  1. 移除也很简单,将属性重新赋值为 undefined / null 即可,如下:

    btn1.onclick = null
    
  2. 而这种现象表明,这种注册事件的方式只能注册一次。看一下示例代码,如下:

    <body>
      <button class="btn1">点击1</button>
    </body>
    <script>
      const btn1 = document.querySelector('.btn1')
    
      // 第一次注册
      btn1.onclick = function () {
        console.log('注册事件一')
      }
    
      // 第二次注册
      btn1.onclick = function () {
        console.log('注册事件二')
      }
    
    </script>
    
  3. 最终我们看一下输出结果,如图:
    在这里插入图片描述

dom2 时代

dom1 中的规范没有涉及到事件,所以是从 dom2 开始

dom2 注册事件

  1. 语法:dom对象.addEventListener

  2. 这中方式与 dom0 的区别是什么?

    1. dom2 可以为某个元素的同一个事件,添加多个处理程序
    2. dom2 允许开发者控制事件的处理阶段,即事件流的执行顺序
  3. addEventListener 方法参数:

    1. 参数一:事件类型/事件名(‘省略 on’)
    2. 参数二:处理函数
    3. 参数三:布尔值(控制是否在捕获阶段,默认 false)
  4. 我们可以来看一下注册方法的具体使用,如下:

    <body>
      <button class="btn">点击</button>
    </body>
    
    <script>
      const btn = document.querySelector('.btn')
    
      btn.addEventListener('click', function () {
        console.log('btn 被点击了')
      })
    </script>
    
  5. 输出很简单,就不在展示了

  6. 我们在多注册一个事件处理程序,看看是否可以生效,如下:

    <body>
      <button class="btn">点击</button>
    </body>
    <script>
      const btn = document.querySelector('.btn')
    
      btn.addEventListener('click', function () {
        console.log('btn 被点击了111')
      })
    
      btn.addEventListener('click', function () {
        console.log('btn 被点击了222')
      })
    
    </script>
    
  7. 输出如图:
    在这里插入图片描述

  8. 对于同一个元素来说,谁先注册谁先处理

  9. 前面有讲到,dom2 的方式是可以让开发者控制事件处理阶段的,默认为冒泡,而要实现这个操作,我们需要使用第三个参数,修改为 true 即可,我们修改为捕获阶段看一下,如下:

    <body>
      <div class="box">
        <button class="btn">点击</button>
      </div>
    </body>
    <script>
      const btn = document.querySelector('.btn')
      const box = document.querySelector('.box')
    
      btn.addEventListener('click', function () {
        console.log('btn 被点击了')
      })
    
      box.addEventListener('click', function () {
        console.log('box 被点击了')
      }, true)
    
      document.documentElement.addEventListener('click', function () {
        console.log('html 被点击了')
      })
    
      document.addEventListener('click', function () {
        console.log('document 被点击了')
      })
    </script>
    
  10. 比如我们这里将 box 设置为 true,那么按照事件流的方式,输出顺序应该是 box --> btn --> html --> document,其中 box 到 btn 属于事件捕获,而 btn 到 document 属于事件冒泡,至于为什么会是这样的顺序,可以查看我的另外一篇文章DOM - 事件之基础概念

  11. 那我们查看一下输出,是否是我们设想的结果,如图:
    在这里插入图片描述

  12. 那按照这个猜测,我们可以将 html 修改为事件捕获,输出如图:
    在这里插入图片描述

  13. 基于此,我们可以进行错开,给 html 和 btn 设置为事件捕获,那么根据触发顺序就是 html --> btn --> box --> document,如图:
    在这里插入图片描述

  14. 同理我们也可以给一个元素注册两个事件,但是运行阶段不一样,也可以改变顺序,如图:
    在这里插入图片描述

  15. 注意:如果这个绑定事件的元素属于目标阶段,那么就不会区分冒泡和捕获阶段,所以第三个参数就会无效

dom2 移除事件

  1. 语法:dom对象.removeEventListener,removeEventListener接收两个参数:

    1. 参数一:事件名
    2. 参数二:移除那个时间处理函数(一个元素可能绑定多个事件处理程序)
  2. 代码如下:

    <body>
      <button class="btn">点击</button>
      <button class="removeBtn">移除</button>
    </body>
    <script>
      const btn = document.querySelector('.btn')
      const removeBtn = document.querySelector('.removeBtn')
    
      // 如果是移除就不能使用匿名函数
      function btnFunc() {
        console.log('btn 被点击了')
    
      }
      btn.addEventListener('click', btnFunc)
    
      // 点击移除 btn 的点击事件
      removeBtn.addEventListener('click', function () {
        // 移除
        btn.removeEventListener('click', btnFunc)
      })
    </script>
    
  3. 结果如图:
    在这里插入图片描述

  4. 所以在 dom2 中移除事件需要具名函数

补充

  1. dom2 在 ie8 及以下不兼容,ie8 中需要使用 attachEvent, detachEvent 进行添加和移除事件,即把 addEventListener 和 removeEventListener 对应替换即可,且不知修改捕获阶段和冒泡阶段

  2. 添加和移除事件时,可以将第三个参数写成一个对象,进行配置,如下:

    <script>
    btn.addEventListener('click', btnFunc, {
        capture: false, // 是否在捕获阶段运行, 默认为 false
        once: true, // 是否只执行一次,默认为 false
    })
    </script>
    
  3. 当然还有一个配置项,passive,当 passive 设置为 true 时,表示事件处理程序不会调用 preventDefault() 来阻止默认行为,这样可以提高滚动性能。相反,当 passive 设置为 false 或未指定时,事件处理程序可以调用 preventDefault() 来阻止默认行为。

  4. passive 配置项的引入是为了解决滚动性能问题。在过去,滚动事件的处理程序通常会调用 preventDefault() 来阻止默认的滚动行为,以实现自定义的滚动效果。然而,这会导致浏览器在滚动期间等待事件处理程序完成,从而降低滚动的流畅性。通过将 passive 设置为 true,浏览器可以知道事件处理程序不会调用 preventDefault(),从而优化滚动性能。这对于处理大量滚动事件的情况特别有用,例如在滚动容器中处理大型列表或表格时。

  5. 前面使用 removeEventListener 移除事件都是默认冒泡的,如果绑定的事件程序是捕获阶段的,移除事件时需要加入第三个参数,设置为 true

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值