使用 querySelectorAll NodeList 循环的多种选择

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 价值 200 美元的免费积分!

在编写原生 JavaScript 时,一个常见的需求是在 DOM 中找到一组元素并循环遍历它们。 例如,找到按钮实例并向它们附加点击处理程序。

const buttons = document.querySelectorAll(".js-do-thing");
// There could be any number of these! 
// I need to loop over them and attach a click handler.

有非常多种方法可以实现这一点。 让我们逐一查看。

forEach

forEach 通常用于数组,有趣的是,querySelectorAll 返回的不是数组,而是 NodeList。 幸运的是,大多数现代浏览器都支持在 NodeList 上使用 forEach

buttons.forEach((button) => {
  button.addEventListener('click', () => {
    console.log("forEach worked");
  });
});

如果您担心 forEach 可能无法在您的 NodeList 上运行,可以先将其扩展为数组

[...buttons].forEach((button) => {
  button.addEventListener('click', () => {
    console.log("spread forEach worked");
  });
});

但我其实不确定这样做是否有帮助,因为似乎不太可能存在支持扩展但 NodeList 上不支持 forEach 的浏览器。 不过,在使用转译时,情况可能会变得奇怪,但我不知道。 无论如何,如果想使用其他特定于数组的函数,例如 .map().filter().reduce(),扩展会比较方便。

一个稍微旧一点的方法是使用这个小技巧接入数组的自然 forEach

[].forEach.call(buttons, (button) => {
  button.addEventListener('click', () => {
    console.log("array forEach worked");
  });
});

Todd Motto 曾经 严厉批评过这种方法,所以请注意。 他建议构建您自己的方法(更新为 ES6)

const forEach = (array, callback, scope) => {
  for (var i = 0; i < array.length; i++) {
    callback.call(scope, i, array[i]); 
  }
};

…我们将其用作

forEach(buttons, (index, button) => {
  console.log("our own function worked");
});

for .. of

浏览器支持 for for .. of 循环看起来相当不错,对我来说,这似乎是一个超级简洁的语法

for (const button of buttons) {
  button.addEventListener('click', () => {
    console.log("for .. of worked");
  });
}

立即创建一个数组

const buttons = Array.prototype.slice.apply(
  document.querySelectorAll(".js-do-thing")
);

现在,您可以使用所有正常的数组函数。

buttons.forEach((button) => {
  console.log("apply worked");
});

旧的 for 循环

如果您需要尽可能大的浏览器支持,使用古老的经典 for 循环并不会令人感到羞愧

for (let i = 0; i < buttons.length; ++i) {
  buttons[i].addEventListener('click', () => {
    console.log("for loop worked");
  });
}

等等! 上面的示例包含箭头函数和 ES6 let。 如果您想更旧一些,并支持旧版 IE 等,您需要…

for (var i = 0; i < buttons.length; ++i) {
  buttons[i].addEventListener('click', function() {
    console.log("for loop worked");
  });
}

如果您使用的是 jQuery,您甚至不必费心….

$(".buttons").on("click", () => {
  console.log("jQuery works");
});

如果您使用的是 React/JSX 设置,您无需考虑这种绑定。

Lodash 也具有 _.forEach,这可能有助于支持旧版浏览器。

_.forEach(buttons, (button, key) => {
  console.log("lodash worked");
});

投票

Twitter 用户

此外,这里有一个示例,其中包含所有这些选项。