一文带你搞懂JavaScript的DOM事件流

一、前言

JavaScript事件流是指事件在DOM结构中传播和触发的顺序。了解事件流的机制对于编写交互性强的网页或应用程序至关重要。事件流包括三个阶段:捕获阶段、目标阶段和冒泡阶段。在捕获阶段,事件从最外层的元素向目标元素进行传播;在目标阶段,事件到达目标元素并触发;在冒泡阶段,事件从目标元素向外层元素进行传播。了解事件流的顺序和机制有助于开发者更好地理解和处理事件,实现所需的交互效果。

二、认识事件流

(1)事件冒泡

首先通过一个案例了解一下这个过程,创建一个container容器,里面包含着一个child容器,并分别给这两个容器添加点击事件。代码如下:

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>事件流title>
  <style>
    *{
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    .container{
      height: 300px;
      width: 300px;
      background: red;
    }
    .container .child{
      height: 100px;
      width: 100px;
      background: #333;
    }
style>
head>
<body>
  <div class="container">
    <div class="child">
    div>
  div>

  <script>
    const containerEl = document.querySelector('.container')
    const childEl = document.querySelector('.child')

    containerEl.addEventListener('click',(e) =>{
      console.log('container被点击了');
    })

    childEl.addEventListener('click',(e) => {
      console.log('child被点击了');
    })
script>
body>
html>

从代码上看,我们给containerEl和childEl使用addEventListener添加点击事件,该方法可以加第三个参数(表示是否在捕获阶段执行,默认false)。现在当我点击child容器时,会先执行child的点击事件,然后再冒泡父元素,触发父元素的事件,所以打印结果如下:
一文带你搞懂JavaScript的DOM事件流_第1张图片
当我只点击了container容器,只会打印“container被点击了”。这就是事件冒泡的原理。

(2)事件捕获

在以上代码的基础上,进行修改,将container的addEventListener的第三个参数设置为true。

containerEl.addEventListener('click',(e) =>{
    console.log('container被点击了');
},true)

当我们点击child容器,可以发现container的点击事件在捕获阶段执行,不会在冒泡阶段执行,打印信息如下:

一文带你搞懂JavaScript的DOM事件流_第2张图片

(3)事件委托

事件委托是一种JavaScript编程模式,通过将事件绑定在父元素上,利用事件冒泡原理,实现对子元素的事件监听和处理。这种方式可以减少事件绑定的数量,提高性能和代码的简洁性,尤其适用于动态添加或大量子元素的情况下。

假设有一个列表,我们需要知道点击的是哪一项,一般普遍的方法是循环这个列表,给每一项都添加点击事件。代码如下:

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>事件委托title>
head>
<body>
  <ul>
    <li>1li>
    <li>2li>
    <li>3li>
    <li>4li>
    <li>5li>
  ul>

  <script>
    const ulEl = document.querySelector('ul')
    const liEl = ulEl.children
    for(let i = 0; i < liEl.length; i++){
      liEl[i].addEventListener('click',(e) => {
        console.log(e.target.textContent);
      })
    }
script>
body>
html>

当我们使用事件委托的方式,只需给父元素ul添加点击事件,通过事件冒泡的原理,父元素可以知道点击的是哪一个li,代码如下:

const ulEl = document.querySelector('ul')
	ulEl.addEventListener('click',(e) => {
	console.log(e.target.textContent);
})

说到这里,我们可以通过e.target获取到目标元素,同时可以通过e.currentTarget获取到处理元素(这里指的是ul),我们通过代码进行验证。

ulEl.addEventListener('click',(e) => {
     console.log('e.target',e.target);
     console.log('e.currentTarget',e.currentTarget)
})

一文带你搞懂JavaScript的DOM事件流_第3张图片
可以看出,相比传统循环添加事件的方式,事件委托的方式减少了事件监听的次数,性能方面较高。

欢迎关注公众号—代码分享站
一文带你搞懂JavaScript的DOM事件流_第4张图片

你可能感兴趣的:(JavaScript,javascript)