想要在多个具有相同类的元素上添加“addEventListener”

12
我希望通过JS事件监听在"onClick"中执行逻辑,但似乎只运行一次?我在所有四个类中都有这个类,但我不知道为什么它似乎只对第一个类有效?
HTML:
<button id='btn-1' type="button" name="first" class="breakdown main-text" onclick="enableButton('btn-2');disableButton('btn-1');show('btn-1')"> Breakdown Start </button>
<button id='btn-2' type="button" name="second" class="breakdown main-text" onclick="enableButton('btn-3');disableButton('btn-2');show('btn-2')" disabled> Repair Start </button>
<button id='btn-3' type="button" name="third" class="breakdown main-text" onclick="enableButton('btn-4');disableButton('btn-3');show('btn-3')" disabled> Repair End </button>
<button id='btn-4' type="button" name="fourth" class="breakdown main-text" onclick="show('btn-4')" disabled> Breakdown Ended </button>

JS:

let button1 = document.querySelector('#btn-1')
let button2 = document.querySelector('#btn-2');
let button3 = document.querySelector('#btn-3');
let button4 = document.querySelector('#btn-4');


const breakdownButton = document.querySelector('.breakdown');
breakdownButton.addEventListener('click', function() {
console.log(this.innerHTML);
});

其他按钮已被禁用。它们的事件监听器除了第一个按钮外将不会被触发。 - kboul
我该如何动态地禁用和重新启用按钮? - Nakul Malhotra
使用事件委托代替分配多个事件监听器,这样更易于维护。例如,使用事件参数target。请参见标签信息什么是DOM事件委托?。这里:addEventListener("click", ({ target }) => { if(target.closest(".breakdown")){ console.log(target.innerHTML); } }); - Sebastian Simon
相关(可能重复):NodeList 上的 addEventListener - Sebastian Simon
3个回答

16

你需要使用 querySelectorAll 方法,它会返回一个集合。现在使用 扩展运算符(三个点)将其转换为数组,并使用 forEach 方法。在 forEach 的回调函数中添加事件监听器。

[...document.querySelectorAll('.breakdown')].forEach(function(item) {
  item.addEventListener('click', function() {
    console.log(item.innerHTML);
  });
   });
<button id='btn-1' type="button" name="first" class="breakdown main-text"> Breakdown Start </button>
<button id='btn-2' type="button" name="second" class="breakdown main-text" disabled> Repair Start </button>
<button id='btn-3' type="button" name="third" class="breakdown main-text" disabled> Repair End </button>
<button id='btn-4' type="button" name="fourth" class="breakdown main-text" disabled> Breakdown Ended </button>

在你的代码片段中,你还附加了内联事件处理程序,这可能是不必要的。

如果目标是启用下一个按钮,则可以从事件处理程序的回调函数中调用一个启用它的函数


1
将扩散到数组中真的有必要吗?在Chrome控制台中似乎可以调用querySelectorAll结果上的forEach - benmccallum
1
不过,遗憾的是,它不能直接在 getElementsByClassName 的结果上调用... - benmccallum
有人知道为什么这个代码可以用 querySelectorAll,但是不能用 document.getElementsByClassName 吗? - S..
因为一个返回 NodeList,另一个返回 HTMLCollection。只有其中一个具有 forEach 方法。 - Sebastian Simon

3
需要使用querySelectorAll,而不是querySelector。并像这样遍历列表。
const breakdownButton = document.querySelectorAll('.breakdown');

// It add event listeners for the first button element. 
// you can use forloop or map function to iterate over the list elements
// and here i used breakdownButton[0] as an example.

breakdownButton[0].addEventListener('click', function() {
  console.log(this.innerHTML);
});

使用像forEach或map这样的迭代函数。我使用了forEach。

const breakdownButton = document.querySelectorAll('.breakdown');
breakdownButton.forEach(function(btn) {
  btn.addEventListener('click', function() {
    console.log();
  });
});

[0] 不会遍历整个列表,它只是取其中的第一个元素。 - Quentin
我们需要为给定的按钮元素添加事件监听器,我已经给出了示例。 - htoniv
没关系,下面是您要翻译的内容:Programming相关内容的翻译 - asking for a friend

2
查看文档了解querySelector

querySelector()返回与指定选择器或选择器组匹配的第一个元素

如果您想匹配多个元素,您需要使用querySelectorAll,并且因为它不返回单个元素,您需要循环遍历结果。

或者,您可以使用事件委托


在某些情况下,一个比另一个更有价值吗?谢谢! - Nakul Malhotra
@NakulMalhotra — 事件委托的好处在我链接的问题中有详细解释。 - Quentin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接