Skip to content
本页目录

DOM 事件处理

DOM 事件处理是 JavaScript 中常用的一项功能,它允许你监听和响应用户与网页元素之间的交互。下面是一些常见的方法和技巧来处理 DOM 事件:

事件

事件是编程语言中的术语,它是用来描述程序的行为或状态的,一旦行为或状态发生改变,便立即调用一个函数。

例如:用户使用【鼠标点击】网页中的一个按钮、用户使用【鼠标拖拽】网页中的一张图片

事件监听

TIP

结合 DOM 使用事件时,需要为 DOM 对象添加事件监听,等待事件发生(触发)时,便立即调用一个函数。

addEventListener 是 DOM 对象专门用来添加事件监听的方法,它的两个参数分别为【事件类型】和【事件回调】。

  • 使用 addEventListener 方法来添加事件监听器:

    js
    function eventHandler() {}
    element.addEventListener('eventName', eventHandler)

    其中 'eventName' 是要监听的事件名称,例如 'click''mouseover''keyup' 等。eventHandler 是一个函数,它会在事件触发时执行。

  • 使用匿名函数来定义事件处理程序:

    js
    element.addEventListener('eventName', function (event) {
      // 事件处理程序的逻辑代码
    })
  • 也可以使用箭头函数来定义事件处理程序:

    js
    element.addEventListener('eventName', (event) => {
      // 事件处理程序的逻辑代码
    })

事件移除

当我们不再需要一个事件监听器时,应该将其从元素上移除,以避免不必要的事件处理。可以使用以下方法来移除事件监听器:

js
element.removeEventListener('eventName', eventHandler)

事件类型

鼠标事件

鼠标事件是指跟鼠标操作相关的事件,如单击、双击、移动等。

事件名作用
click当用户点击鼠标左键时触发。
dblclick当用户双击鼠标左键时触发。
mousedown当用户按下鼠标按钮时触发。此事件在按下任何鼠标按钮时都会触发,包括左键、中键和右键。
mouseup当用户释放鼠标按钮时触发。
mousemove当用户移动鼠标指针时触发。该事件在鼠标指针每次移动时都会触发,可以用于实时跟踪鼠标位置。
mouseover当鼠标指针进入元素的可见区域时触发。
mouseout当鼠标指针离开元素的可见区域时触发。
mouseenter当鼠标指针进入元素的可见区域时触发,与 mouseover 不同的是,mouseenter 不会在子元素上触发。
mouseleave当鼠标指针离开元素的可见区域时触发,与 mouseout 不同的是,mouseleave 不会在子元素上触发。
contextmenu当用户在元素上点击鼠标右键时触发,通常用于显示自定义的上下文菜单。
wheel当用户使用鼠标滚轮时触发。
js
const box = document.querySelector('.box')

// 监听鼠标是移入当前 DOM 元素
box.addEventListener('mouseenter', function () {
  // 修改文本内容
  this.innerText = '鼠标移入了...'
  // 修改光标的风格
  this.style.cursor = 'move'
})

// 监听鼠标是移出当前 DOM 元素
box.addEventListener('mouseleave', function () {
  // 修改文本内容
  this.innerText = '鼠标移出了...'
})

键盘事件

js
const input = document.querySelector('input')
// 1. 键盘事件
// input.addEventListener('keydown', function () {
//   console.log('键盘按下了')
// })
// input.addEventListener('keyup', function () {
//   console.log('键盘谈起了')
// })
// 2. 用户输入文本事件  input
input.addEventListener('input', function () {
  console.log(input.value)
})

焦点事件

js
const input = document.querySelector('input')
input.addEventListener('focus', function () {
  console.log('有焦点触发')
})
input.addEventListener('blur', function () {
  console.log('失去焦点触发')
})

文本框输入事件

  • input 事件:当用户在文本框中输入、删除或修改文本时触发。无论是键盘输入、粘贴、剪切还是使用其他输入方法,只要文本框内容发生变化,就会触发 input 事件。
  • change 事件:当文本框内容发生改变并失去焦点时触发。与 input 事件不同,change 事件在用户完成输入并离开文本框时才会触发。
  • keydown 事件:当用户按下键盘上的任意键时触发。可以使用该事件来监测实时的键盘输入,并进行相应处理。
  • keyup 事件:当用户释放键盘上的按键时触发。类似于 keydown 事件,keyup 事件也可以用于检测键盘输入,并做出相应的响应。
  • keypress 事件:当用户按下键盘上的字符键时触发。与 keydownkeyup 事件不同,keypress 事件只在按下字符键时才触发,不会在按下非字符键(如 Shift、Ctrl 等)时触发。

事件对象

  • 事件处理程序的第一个参数是事件对象 event,它包含有关事件的信息,例如事件类型、目标元素等。你可以在事件处理程序中使用这些信息来执行逻辑操作。
js
const btn = document.querySelector('button')
btn.addEventListener('click', function (e) {
  console.log(e)
})

在事件处理程序中,可以通过事件对象访问有关事件的详细信息。事件对象提供了许多属性和方法,以帮助我们处理事件。以下是一些常用的事件对象属性:

  • event.target:触发事件的目标元素。
  • event.type:事件类型。
  • event.preventDefault():阻止事件的默认行为。例如阻止表单提交或超链接跳转。
  • event.stopPropagation():停止事件的传播。

事件冒泡和事件捕获

  • 事件冒泡:默认情况下,事件会从触发它的元素向上冒泡到祖先元素。你可以使用 event.stopPropagation() 方法来停止事件冒泡。
html
<body>
  <h3>事件流</h3>
  <p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p>
  <div class="outer">
    <div class="inner">
      <div class="child"></div>
    </div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer')
    const inner = document.querySelector('.inner')
    const child = document.querySelector('.child')

    // html 元素添加事件
    document.documentElement.addEventListener('click', function () {
      console.log('html...')
    })

    // body 元素添加事件
    document.body.addEventListener('click', function () {
      console.log('body...')
    })

    // 外层的盒子添加事件
    outer.addEventListener('click', function () {
      console.log('outer...')
    })

    // 中间的盒子添加事件
    outer.addEventListener('click', function () {
      console.log('inner...')
    })

    // 内层的盒子添加事件
    outer.addEventListener('click', function () {
      console.log('child...')
    })
  </script>
</body>
  • 事件捕获:可以通过将第三个参数设置为 true 来启用事件捕获模式。在事件捕获模式下,事件将从祖先元素开始,向下传播到触发事件的元素。
html
<body>
  <h3>事件流</h3>
  <p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p>
  <div class="outer">
    <div class="inner"></div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer')
    const inner = document.querySelector('.inner')

    // 外层的盒子
    outer.addEventListener(
      'click',
      function () {
        console.log('outer...')
      },
      true
    ) // true 表示在捕获阶段执行事件

    // 中间的盒子
    outer.addEventListener(
      'click',
      function () {
        console.log('inner...')
      },
      true
    )
  </script>
</body>

常见事件类型

以下是一些常见的 DOM 事件类型:

  • 鼠标事件:clickmouseovermouseoutmousemove 等。

  • 键盘事件:keyupkeydownkeypress 等。

  • 表单事件:submitinputchangefocusblur 等。

  • 页面加载事件:loadDOMContentLoaded 等。

  • 视图事件:resizescroll 等。

  • 触摸事件:touchstarttouchendtouchmove 等。

事件委托

JavaScript 事件委托是一种利用事件冒泡原理来简化事件处理的技术。通过将事件监听器绑定到一个父元素上,然后利用事件冒泡机制,从父元素中捕获和处理子元素触发的事件。这样可以减少事件处理程序的数量,并且可以动态地处理后续添加的子元素,提高性能和代码的可维护性。

使用事件委托的过程如下:

  1. 选择一个合适的父元素,该元素包含你希望委托处理的子元素。

  2. 将事件监听器绑定到父元素上,监听你希望处理的事件类型。

  3. 在事件处理程序中,通过判断事件的目标元素(event.target)来确定是哪个子元素触发了事件。

  4. 根据需要对目标元素进行处理,或者根据目标元素的特定属性或位置来执行相应操作。

通过事件委托,你只需要在父元素上绑定一个事件监听器,无论子元素的数量如何变化,只要满足选择器条件的子元素触发了事件,都可以被捕获和处理。这样可以避免为每个子元素分别绑定事件监听器,从而减少内存占用和提高性能。

事件委托还可以解决动态添加或删除的子元素无法自动绑定事件监听器的问题。因为委托是基于事件冒泡的,所以后续添加的子元素也能够触发绑定在父元素上的事件监听器。

总结起来,事件委托是一种利用事件冒泡机制,在父元素上统一绑定事件监听器,通过事件的目标元素来判断并处理子元素的事件,提供了更简洁、高效的事件处理方式。

html
<body>
  <ul id="myList">
    <li>选项1</li>
    <li>选项2</li>
    <li>选项3</li>
    <li>选项4</li>
    <li>选项5</li>
  </ul>

  <script>
    // 获取父元素
    var myList = document.getElementById('myList')

    // 绑定点击事件监听器到父元素
    myList.addEventListener('click', function (event) {
      // 检查点击的目标元素是否为列表项
      if (event.target.tagName === 'LI') {
        // 获取列表项的文本内容
        var text = event.target.textContent
        // 打印文本内容
        console.log(text)
      }
    })
  </script>
</body>

lemon's personal blog.