DOM 事件与事件委托

DOM 事件与事件委托

本文写于 2020 年 5 月 28 日

先思考一个问题:我们如何给一百个 button 添加点击事件?

遍历?

那岂不是要添加一百个监听器?

这就需要事件委托了。

其实这根本不是一个很难的概念,看下去,本文并不长。

1. 点击事件

现在我们拥有三个元素,他们嵌套成为爷爷、爸爸、儿子:

<div class='grandpa'>
  <div class='father'>
    <div class='son'></div>
  </div>
</div>

然后分别给他们仨添加不同的三个事件监听。

因为事件冒泡,我们能知道他们都会执行,并且会按照一定顺序执行。

但是不同浏览器的顺序是不一样的

IE 认为应该调用 .son 的事件,网景认为应该调用 .grandpa

后来 2002 年,W3C 发布了标准:

  • 先按照从外向内——事件捕获
  • 在按照从内向外——事件冒泡

整个过程就是——有监听函数就调用,没有就跳过。

开发者可以自己选择把最外层的事件,放在捕获阶段还是冒泡阶段。

如何选择呢?其实就是我们最熟悉的addEventListener

我们经常会用它去绑定事件,我们一般都只会传入两个参数。

可实际上这个函数有 3 个参数

我们可以在第三个参数,放置一个布尔值,例如:xxx.addEventListener('click', fn, bool)

如果是true,则是捕获方式(从外向内);如果不写,或者是falsy值,则是冒泡(从内向外)

顺序问题

上面说了,先捕获后冒泡。

那我同时给一个元素,先挂一个冒泡,再挂一个捕获——谁先触发?

谁先写,谁先触发,因为他们是同级的

可以取消吗?

捕获不可以取消,但是冒泡可以取消。(有些事件不能取消,比如滚动事件)

e.stopPropagation()中断冒泡。

2. 事件委托

回到我们刚开始的问题:我们如何给一百个 button 添加点击事件?

肯定不是遍历。

我们可以直接给父元素添加事件,例如:

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

这里看到,我们传入了一个 e,这个 e 可以尝试打印出来,就会发现其实是MouseEvent

这是一个对象,里面有各种各样的数据,比如我们需要的target

target就是用户所点击的元素!

也就是说如果 father 有 10 个孩子,从 child1 一直到 child10,我们点谁,这个 target 就是谁

e.currentTarget呢,和e.target是有区别的!

简单来说呢 target被操作的元素currentTarget被监听的元素

在这个例子中,currentTarget 恒为 father,target 则会随着点击发生改变。

最后说一下,JS 其实是不支持事件的!支持事件的是浏览器,addEventListener 是浏览器的 DOM 提供的。

(完)

原文地址:https://www.cnblogs.com/xhyccc/p/13442195.html