You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

addEventListener绑定同class元素点击事件仅首次生效原因

问题根本原因

你的代码失效核心原因是对document.querySelector()的行为存在误解:该方法只会返回DOM中第一个匹配选择器规则的元素,不会自动匹配所有符合条件的元素。

你写的document.querySelector('.emoji').addEventListener(...),实际只给页面上第一个带emoji类的元素(也就是初始状态下显示的🙉)绑定了点击事件,第二个emoji元素(🙈)从始至终没有绑定任何点击回调。

代码实际执行流程如下:

  • 页面初始加载时,第一个emoji携带active类,覆盖默认的display: none样式处于可见状态;第二个emoji无active类处于隐藏状态,此时只有可见的第一个emoji能响应点击。
  • 第一次点击第一个emoji时,绑定的回调正常执行:两个元素的active类被切换,第一个emoji失去active类变为隐藏,第二个emoji获得active类变为可见。
  • 此时页面上可点击的可见元素是第二个emoji,但你从未给它绑定过点击事件,所以后续所有点击都不会触发回调,表现出来就是代码仅首次点击生效。

你之前开发计算器时遇到的"仅第一个绑定的按钮点击生效"问题,根因完全相同,都是误用querySelector只给第一个匹配元素绑定了事件。

修复方案

你提到的"分别给.open、.closed元素绑定事件"的方案之所以有效,本质就是让两个emoji元素都带上了点击回调,逻辑和下面的方案1一致。

方案1:给所有emoji元素绑定事件

使用document.querySelectorAll()选中所有带emoji类的元素,遍历后逐个绑定事件即可:

// 选中所有.emoji元素,遍历绑定点击事件
document.querySelectorAll('.emoji').forEach(emojiEl => {
  emojiEl.addEventListener('click', () => {
    document.querySelector('.open').classList.toggle('active');
    document.querySelector('.closed').classList.toggle('active');
  })
})

方案2:事件委托(更优写法)

不需要给每个emoji单独绑事件,直接把事件绑定在共同的父容器上,利用事件冒泡机制处理点击即可,后续如果新增同类emoji元素也不需要重复绑定:

// 这里把事件绑在body上,也可以绑在两个emoji的共同父容器上
document.body.addEventListener('click', (e) => {
  // 判断点击触发源是否是emoji元素,是则执行切换
  if (e.target.classList.contains('emoji')) {
    document.querySelector('.open').classList.toggle('active');
    document.querySelector('.closed').classList.toggle('active');
  }
})

补充说明:你写的CSS逻辑没有问题,问题100%出在JS的元素选择和事件绑定环节。

内容的提问来源于stack exchange,提问作者Wojtek1911

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 14:42:32