JavaScript事件监听之事件流(捕获阶段实现 + 阻止事件流传播 + 阻止元素默认行为、mouse鼠标事件、事件委托)

1. 捕获阶段实现 + 阻止事件流传播 + 阻止元素默认行为

默认只在冒泡阶段触发事件。可以选择不在冒泡阶段触发事件,而在捕获阶段触发事件。语法: 元素对象.addEventListener('事件类型', 要执行的函数, 是否在捕获阶段触发事件),是否在捕获阶段触发事件默认为false。L0旧版事件监听只有冒泡,没有监听

示例:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
  <title>Title</title>

  <style>
    .father {
      width: 200px;
      height: 200px;
      background-color: pink;
    }

    .son {
      width: 100px;
      height: 100px;
      background-color: purple;
    }
  </style>

</head>
<body>

  <div class="father">
    <div class="son"></div>
  </div>

  <script>

      document.addEventListener('click', function (e) {
        alert('我是爷爷')
        
        // e.stopPropagation()
        // e.preventDefault()
      }, true)

      const father = document.querySelector('.father')
      father.addEventListener('click', function () {
        alert('我是爸爸')
      }, true)

      const son = document.querySelector('.son')
      son.addEventListener('click', function (e) {
        alert('我是儿子')

        // e.stopPropagation()
        // e.preventDefault()
      }, true)

  </script>
</body>
</html>

如下。点击紫色的小盒子,先弹出我是爷爷,再弹出我是爸爸,最后弹出我是儿子
事件捕获效果
如果addEventListener的第三个参数都是false(默认),则点击紫色的小盒子,先弹出我是儿子,再弹出我是爸爸,最后弹出我是爷爷

阻止事件流传播

  • 捕获阶段:可以在爷爷的事件监听函数中,添加e.stopPropagation()。这样点击紫色的小盒子,只弹出我是爷爷
  • 冒泡阶段:可以在儿子的事件监听函数中,添加e.stopPropagation()。这样点击紫色的小盒子,只弹出我是儿子

阻止默认行为
可以使用e.preventDefault()来阻止元素的默认行为。如:

  • 在a链接的监听事件中,阻止链接的跳转
  • form表单的监听事件中,阻止表单域跳转

2. mouseover/mouseout和mouseenter/mouseleave的区别

  • mouseover: 鼠标进入该元素、或鼠标从子元素进入该元素、或鼠标从该元素进入子元素(子元素事件流冒泡),都会触发事件
  • mouseout: 鼠标离开该元素、或鼠标离开该元素进入子元素、或鼠标离开子元素进入该元素(子元素事件流冒泡),都会触发事件
  • mouseenter: 只有鼠标进入该元素,会触发事件
  • mouseleave: 只有鼠标离开该元素,会触发事件

示例:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
  <title>Title</title>

  <style>
    .father {
      width: 200px;
      height: 200px;
      background-color: pink;
    }

    .son {
      width: 100px;
      height: 100px;
      background-color: purple;
    }
  </style>
</head>
<body>

  <div class="father">
    <div class="son"></div>
  </div>
  <script>
    const father = document.querySelector('.father')
    const son = document.querySelector('.son')
    father.addEventListener('mouseover', function () {
      console.log('鼠标进入父亲')
    })
    father.addEventListener('mouseout', function () {
      console.log('鼠标离开父亲')
    })
  </script>
</body>
</html>

mouseover和mouseout效果如下:

  1. 鼠标移入粉色的大盒子,控制台打印【鼠标进入父亲】
  2. 鼠标从粉色的大盒子移入紫色的小盒子,先打印【鼠标离开父亲】,再打印【鼠标进入父亲】
  3. 鼠标从紫色的小盒子移入粉色的大盒子,先打印【鼠标离开父亲】,再打印【鼠标进入父亲】
  4. 鼠标移出粉色的大盒子,控制台打印【鼠标离开父亲】
    mouseover和mouseout效果
    将html文件中的mouseover改成mouseenter,mouseout改成mouseleave的效果如下:
  5. 鼠标移入粉色的大盒子,控制台打印【鼠标进入父亲】
  6. 鼠标从粉色的大盒子移入紫色的小盒子,无消息打印
  7. 鼠标从紫色的小盒子移入粉色的大盒子,无消息打印
  8. 鼠标移出粉色的大盒子,控制台打印【鼠标离开父亲】
    mouseenter和mouseleave效果

3. 事件委托

如果ul下面有2个li,我们想给每个li绑定相同的点击事件。以前我们都是通过for循环给每个li绑定监听事件,这样效率非常低

可以只给li的父亲 ul绑定点击事件,当点击其中一个li的时候,默认会冒泡触发ul的点击事件。然后通过e.taget获取到点击的这个li,对这个li的样式进行改变

所以将所有的事件监听,都委托给元素的父亲进行监听,就是事件委托

示例:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
  <title>Title</title>

</head>
<body>

  <ul>
    <li>第1个孩子</li>
    <li>第2个孩子</li>
    <p>我不需要改变颜色</p>
  </ul>
  <script>
    const ul = document.querySelector('ul')
    ul.addEventListener('click', function (e) {
      // 只有li才改变颜色
      if (e.target.tagName === 'LI') {
        e.target.style.color = 'red'
      }
    })
  </script>
</body>
</html>

如下所示。点击第一个li会变成红色,点击p不会变色

事件委托效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值