JavaScript向多个元素添加事件监听器

911 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第29天,点击查看活动详情

如果您曾经使用过原生 Javascript,你可能熟悉使用以下公式向元素添加事件侦听器:

let element = document.querySelector('#button');

element.addEventListener('click', () => {
    console.log('some event content here...')
})

当然,上面的代码会触发一个在触发时触发的函数#button。但有时,您需要为多个元素添加事件侦听器——例如,页面上存在的每个按钮。您可能已经发现,即使页面上有多个元素,上述方法也只会将您的事件添加到一个元素 - 第一个元素。是什么赋予了?

这个问题addEventListener只适用于向一个 DOM 元素添加事件 - 并且也querySelector只匹配一个元素。那么如何为页面上的多个元素添加事件监听器呢?让我们看看解决方案。

向多个元素添加事件侦听器

querySelector我们将使用querySelectorAll匹配页面上的所有元素,而不是使用。下面的代码返回一个类型的项目NodeList,由所有匹配的 DOM 元素组成.button要将事件添加到每个元素,我们将需要遍历我们的每个匹配的元素querySelector,并为每个元素添加事件:

let elements = document.querySelectorAll('.button');

Javascript 很奇怪,因为它不会将 DOM 元素作为简单数组返回 - 它会将它们作为NodeList

在现代浏览器中,NodeLists 的行为很像数组,因此我们可以使用它forEach来遍历每个数组。要为每个事件添加一个事件.button,我们需要使用forEach. 因此向click所有.button元素添加事件如下所示:

let elements = document.querySelectorAll('.button');

let clickEvent = () => {
    console.log('some event content here...')
}
elements.forEach((item) => {
    item.addEventListener('click', clickEvent)
});

但是,在 Internet Explorer 等较旧的浏览器中, sforEach上不存在NodeList。尽管这在现代不是问题,但您可能会发现将结果querySelectorAll更改为数组并循环遍历的代码。这实现了同样的事情,但这意味着我们正在循环遍历数组,而不是NodeLists。

let elements = document.querySelectorAll('.button');

let clickEvent = () => {
    console.log('some event content here...')
}
Array.prototype.forEach.call(elements, (item) => {
    item.addEventListener('click', clickEvent);
});

事件委托方法

实现此目的的另一种方法是通过事件委托。这是您将点击事件分配给父级的地方,然后检查用户在父级中单击的位置。这是可以做到的,因为事件冒泡到 Javascript 中的父元素。这也意味着您只需要编写一个函数,而不是循环遍历并将函数添加到多个元素。

为此,我们使用e.target跟踪实际点击了哪个元素 - 因为e.target保存了有关触发初始事件的 DOM 元素的信息。

鉴于我们有一些这样的 HTML:

<div id="holder">
    <div class="button">Hi</div>
    <div class="button">Hi</div>
    <div class="button">Hi</div>
</div>

我们可以添加一个事件并检查是否单击#holder了该类的任何项目。.button这更有效,意味着我们不必使用fororforEach循环:

let element = document.getElementById('holder');

element.addEventListener('click', (e) => {
  if(e.target.classList.contains('button')) {
    console.log('some event content here...');
  }
});