如何使用 JavaScript 同时选择多个具有不同类名的 CSS 元素

本文详解如何用 document.queryselectorall() 正确选择多个带有不同组合类名的 dom 元素,并批量操作,解决因误传多个参数导致选择失败的常见问题。

在 JavaScript 中,document.querySelector() 和 document.querySelectorAll() 是最常用的 DOM 查询方法,但二者行为有本质区别:前者仅返回第一个匹配元素(单个 Element),后者返回所有匹配元素组成的静态 NodeList(类似数组)。你当前代码的问题根源在于错误地将多个选择器作为独立参数传入 querySelector():

// ❌ 错误:querySelector 不支持多个参数,只识别第一个字符串
document.querySelector('.icon-bar.bar-top', '.icon-bar.bar-middle', '.icon-bar.bar-bottom');

同时,querySelectorAll() 本身是支持多组选择器的——但必须合并为一个字符串,用英文逗号分隔,而非多个参数:

// ✅ 正确:单个字符串,逗号分隔多个复合选择器
const iconBars = document.querySelectorAll(
  '.icon-bar.bar-top, .icon-bar.bar-middle, .icon-bar.bar-bottom'
);

注意:每个选择器都需完整、准确。例如 .icon.bar-bottom 在你的 HTML 中实际是 .icon-bar.bar-bottom(中间无空格),若写成 .icon.bar-bottom 将无法匹配——因为这表示同时拥有 icon 和 bar-bottom 两个类,而你的元素类名为 icon-bar 和 bar-bottom。

选中后,需遍历 NodeList 对每个元素单独操作。推荐使用 forEach()(现代浏览器原生支持):

window.addEventListener('scroll', () => {
  const scrollY = window.scrollY;
  if (scrollY >= 46) {
    iconBars.forEach(el => el.classList.add('hero-icon-bar-scroll'));
  } else if (scrollY < 56) {
    iconBars.forEach(el => el.classList.remove('hero-icon-bar-scroll'));
  }
});

⚠️ 注意事项:

  • querySelectorAll() 返回的是 NodeList,不是 Array,因此不能直接调用 map()、filter() 等数组方法(除非用 [...iconBars] 展开或 Array.from(iconBars) 转换);
  • 类名拼写与 HTML 中严格一致(区分大小写、连字符、空格);
  • 若元素动态插入,需确保查询时机在 DOM 渲染完成后(如放在 DOMContentLoaded 事件中);
  • 性能敏感场景下,可缓存 iconBars 结果,避免每次滚动都重复查询。

总结:多元素选择 ≠ 多参数传入;而是「一个字符串 + 多个逗号分隔的选择器」,再配合循环操作。掌握这一模式,即可高效统一控制导航图标、按钮组、卡片列表等任意批量 DOM 元素。