带有 classList 的 querySelectorAll() 上的 addEventListener

IT技术 javascript addeventlistener
2021-03-12 19:05:16

我正在尝试添加一个事件侦听器,但没有结果。我知道 JavaScript 具有提升功能,但我相信除了正确的解决方案外,我尝试了所有其他方法。

const cbox = document.querySelectorAll(".box");
function doit() {
  for (let i = 0; i < cbox.length; i++){
    cbox[i].classList.add("red");
  }
}
cbox.addEventListener("click", doit, false);

有人能发现我犯的错误吗?

3个回答

代码和您提供的链接之间存在一些不同之处。doit()里面没有任何功能

您已附加addEvenListenerNodeListin cbox.addEventListener("click",.....,您必须遍历列表并将事件附加到当前元素:

请尝试以下操作:

const cbox = document.querySelectorAll(".box");

 for (let i = 0; i < cbox.length; i++) {
     cbox[i].addEventListener("click", function() {
       cbox[i].classList.toggle("red");
     });
 }
*,
html,
body {
    padding: 0;
    margin: 0;
}

.box {
    width: 10rem;
    height: 10rem;
    background-color: yellowgreen;
    float: left;
    position: relative;
    margin: 0.5rem;
    transition: .5s all;
}

h3 {
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.box:not(:first-child) {
    margin-left: 1rem;
}

.red {
    background-color: orangered;
}
<div id="box1" class="box box1">
    <h3>Box 1</h3>
</div>
<div id="box2" class="box box2">
    <h3>Box 2</h3>
</div>
<div id="box3" class="box box3">
    <h3>Box 3</h3>
</div>
<div id="box4" class="box box4">
    <h3>Box 4</h3>
</div>

您还可以使用Array.prototype.forEach()witharrow function语法,让您以更少的代码实现相同的目标:

let cbox = document.querySelectorAll(".box");
cbox.forEach(box => {
  box.addEventListener('click', () => box.classList.toggle("red"));
});
*,
html,
body {
    padding: 0;
    margin: 0;
}

.box {
    width: 10rem;
    height: 10rem;
    background-color: yellowgreen;
    float: left;
    position: relative;
    margin: 0.5rem;
    transition: .5s all;
}

h3 {
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.box:not(:first-child) {
    margin-left: 1rem;
}

.red {
    background-color: orangered;
}
<div id="box1" class="box box1">
    <h3>Box 1</h3>
</div>
<div id="box2" class="box box2">
    <h3>Box 2</h3>
</div>
<div id="box3" class="box box3">
    <h3>Box 3</h3>
</div>
<div id="box4" class="box box4">
    <h3>Box 4</h3>
</div>

虽然此代码可能会回答问题,但提供有关如何和/或为什么解决问题的附加上下文将提高答案的长期value。
2021-04-16 19:05:16
谢谢。但就性能问题而言,如果数组中有 20 个项目,该事件是否会触发 20 次?每个元素一个。?
2021-04-21 19:05:16
.querySelectorAll()不返回 aHTMLCollection而是 aNodeList
2021-04-23 19:05:16
@EvangelosK.,是的,你是对的。您必须使用循环将事件侦听器附加到每个元素.....谢谢。
2021-04-27 19:05:16
因此,如果它是某种列表,则意味着我们也可以在元素 cbox 上使用 foreach 循环。
2021-04-28 19:05:16

ES6 让这更简单一点:

document.querySelectorAll(".box").forEach(box => 
  box.addEventListener("click", () => box.classList.toggle("red"))
)

示例实现:

document.querySelectorAll(".box").forEach(box => 
  box.addEventListener("click", () => box.classList.toggle("red"))
)
.box {
    width: 5rem;
    height: 5rem;
    background-color: yellowgreen;
    display: inline-block;
}

.box.red {
    background-color: firebrick;
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>

这是一个使用 ES6 符号的更简洁的解决方案
2021-05-10 19:05:16

您可以forEach在类上使用或使用事件委托

const cboxes = document.querySelectorAll(".box");
function doit() {
    ... do something ...
}
cboxes.forEach(
  function(cbox) {
   cbox.addEventListener("click", doit,false);
  }
);

请注意,我更改了您的变量名称。

事件委托

HTML:

<div id="parent">
  <div id="box1" class="box box1">
    <h3>Box 1</h3>
  </div>
  <div id="box2" class="box box2">
      <h3>Box 2</h3>
  </div>
  <div id="box3" class="box box3">
      <h3>Box 3</h3>
  </div>
  <div id="box4" class="box box4">
      <h3>Box 4</h3>
  </div>
</div>

JS部分:

const parent = document.querySelector("#parent");

parent.addEventListener('click', (e) => {
  e.target.classList.add('red');
  console.log(e.target);
});

事件委托要好得多,它使用的资源更少,因为您只使用 1 个事件侦听器而没有 for 循环。

parent.addEventListener('click', (e) => { const tgt = e.target; if (tgt.classList.contains('box')) tgt.classList.add('red'); console.log(tgt.id); });
2021-04-25 19:05:16
2021-04-26 19:05:16
使 forEach 在 <= IE11 中工作的简单 polyfill 修复是: NodeList.prototype.forEach = Array.prototype.forEach;
2021-05-02 19:05:16
Array.prototype.forEach !== NodeList.prototype.forEach
2021-05-08 19:05:16
或者您可以像这样使用数组展开运算符: [...document.querySelectorAll(".box")]
2021-05-08 19:05:16