跳至主要內容

概述

Yang大约 4 分钟

事件 是某事发生的信号,所有的 DOM 节点都生成这样的信号

  • 为了对事件作出响应,需分配一个 处理程序,一个在事件发生时运行的函数

  • 处理程序可以设置在 HTML 中名为 on<event> 的属性中

  • elem.onclick = null:移除一个事件处理程序

相关文档

事件对象(event)

当事件发生时,浏览器会创建一个 event 对象,将详细信息放入其中,并将其作为参数传递给处理程序

event.type

事件类型,例如 click

event.currentTarget

处理事件的元素,与 this 相同

除非处理程序是一个箭头函数,或者它的 this 被绑定到了其他东西上,之后可以从 event.currentTarget 获取元素

event.clientX / event.clientY

指针事件(pointer event)的指针的窗口相对坐标

addEventListener

注册 click 事件

  • 同一元素的同一阶段的监听器按其设置顺序运行

  • 要移除处理程序,removeEventListener 需要同一阶段

  • 语法:element.addEventListener(event, handler[, options]);

    • event:事件名
    • handle:处理程序(函数)
    • options:可选参数对象,属性如下
      • once:如果为 true,会在事件被触发后删除监听器
      • capture:事件处理的阶段,由于历史原因,options 也可以是 false/true,它与 {capture: false/true} 相同
        • 如果为 false(默认值),则在冒泡阶段设置处理程序
        • 如果为 true,则在捕获阶段设置处理程序
      • passive:如果为 true,那么处理程序将不会调用 preventDefault(),告诉浏览器该行为不会被阻止。这对于某些移动端的事件(像 touchstart 和 touchmove)很有用,用以告诉浏览器在滚动之前不应等待所有处理程序完成
<button id="btn">测试事件</button>
<script type="text/javascript">
  var oBtn = document.getElementById('btn')
  oBtn.addEventListener('click',btnClick,{once:true})
  function btnClick(){
    console.log('click')
  }
</script>

将对象作为处理程序

addEventListener 接收一个对象 obj 作为处理程序时,在事件发生时,它就会调用 obj.handleEvent(event) 来处理事件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
      #div {
        width: 200px;
        height: 200px;
        border: 1px solid #000;
        background: #f3f3f3;
        text-align: center;
        line-height: 200px;
        font-size: 24px;
      }
    </style>
  </head>
  <body>
    <div id="div"></div>
    <script type="text/javascript">
      class Menu {
        handleEvent(event) {
          const method = `on${event.type[0].toUpperCase()}${event.type.slice(1)}`
          this[method](event)
        }
        onMousedown(event) {
          console.log(event.target)
          event.target.innerHTML = 'mousedown'
        }
        onMouseup(event) {
          event.target.innerHTML = 'mouseup'
        }
        onMouseout(event) {
          event.target.innerHTML = ''
        }
      }
      var oDiv = document.getElementById('div')
      var menu = new Menu()
      oDiv.addEventListener('mousedown', menu)
      oDiv.addEventListener('mouseup', menu)
      oDiv.addEventListener('mouseout', menu)
    </script>
  </body>
</html>

与 onclick 的区别

  • 直接写 onclick 事件在同一时间只能指向唯一对象,后面写的会覆盖前面的
  • addEventListener 可以给一个事件注册多个 listener,且均可执行
  • addEventListener 可以使用 removeEventListener 清除
  • JQuery 与 addEventListener 一样可以注册多个事件,且均可执行
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button id="clickme">Click me!</button>
    <div id="message"></div>
    <script src="js/jquery.js"></script>
    <script>
      var oBtn = document.getElementById('clickme')
      function btnClick() {
        console.log('button click')
      }
      function btnClickClick() {
        console.log('button click click')
      }
      /**
       * onclick 直接绑定
       */
      oBtn.onclick = btnClick
      oBtn.onclick = btnClickClick

      /**
       * addEventListener 注册事件
       */
      oBtn.addEventListener('click', btnClick)
      oBtn.addEventListener('click', btnClickClick)

      // 清除 addEventListener 注册的事件
      setTimeout(() => {
        oBtn.removeEventListener('click', btnClickClick)
        console.log('removeEventListener success')
      }, 5000)

      /**
       * JQuery 绑定事件
       */
      $('#clickme').click(btnClick)
      $('#clickme').click(btnClickClick)
    </script>
  </body>
</html>

例子

球体区域点击定位

小球在矩形内部,点击矩形任意一点,将球中心定位到该店,并且小球仅在矩形内部移动

<!DOCTYPE HTML>
<html>

  <head>
    <meta charset="utf-8">
    <style>
      #field {
        position: relative;
        width: 300px;
        height: 300px;
        border: 10px solid black;
        background: #00FF00;
        overflow: hidden;
        cursor: pointer;
      }

      #ball {
        position: absolute;
        left: 0;
        top: 0;
        width: 40px;
        height: 40px;
        transition: all 1s;
      }
    </style>
  </head>

  <body style="height:2000px">

    Click on a field to move the ball there.
    <br>


    <div id="field">
      <img src="https://en.js.cx/clipart/ball.svg" id="ball">
    </div>

    <script>
      var oField = document.getElementById('field')
      oField.addEventListener('click', handleChange)

      function handleChange(event) {

        // div相对于窗口的坐标
        let fieldCoords = this.getBoundingClientRect();
        console.log(fieldCoords)

        // top: 点相对于窗口的纵坐标 - 矩形顶部的纵坐标 - 矩形上边框 - 球高度的一半
        // left: 点相对于窗口的横坐标 - 矩形左边缘的横坐标 - 矩形左边框 - 球宽度的一半
        let ballCoords = {
          top: event.clientY - fieldCoords.top - field.clientTop - ball.clientHeight / 2,
          left: event.clientX - fieldCoords.left - field.clientLeft - ball.clientWidth / 2
        };

        // 保证球体顶部边缘在矩形内部
        if (ballCoords.top < 0) ballCoords.top = 0;

        // 保证球体左部边缘在矩形内部
        if (ballCoords.left < 0) ballCoords.left = 0;


        // 保证球体右部边缘在矩形内部
        if (ballCoords.left + ball.clientWidth > field.clientWidth) {
          ballCoords.left = field.clientWidth - ball.clientWidth;
        }

        // 保证球体底部边缘在矩形内部
        if (ballCoords.top + ball.clientHeight > field.clientHeight) {
          ballCoords.top = field.clientHeight - ball.clientHeight;
        }

        // 设置球体样式
        ball.style.left = ballCoords.left + 'px';
        ball.style.top = ballCoords.top + 'px';
      }
    </script>

  </body>
</html>
上次编辑于:
贡献者: sunzhenyang