You need to enable JavaScript to run this app. 为什么点击事件监听器仅生效一次?如何实现点击任意li元素执行函数
优惠活动
大模型
产品
解决方案
定价
更多

为什么点击事件监听器仅生效一次?如何实现点击任意li元素执行函数

问题核心原因

你的代码存在两处逻辑错误,直接导致点击事件无法对所有li生效:

  • HTML规范明确要求页面内的id值必须全局唯一,你给三个<li>标签都设置了相同的id="listItem",而document.getElementById()只会返回文档中第一个匹配该id的元素(也就是内容为"One"的li),剩余两个li完全未被获取,自然也无法绑定点击事件。
    你原有代码中的CSS规则ul li {cursor: pointer;}没有问题,所有li都会显示可点击的手型鼠标样式,这也容易造成“事件已经绑定但只生效一次”的错觉——实际只有第一个li能响应点击,其余两个li点击无任何反馈。
  • 事件回调逻辑写死了操作目标:就算能正确获取所有li元素,当前clickTodo函数内部直接修改listItem变量指向的固定元素样式,不会响应实际被点击的节点,即便给多个元素绑定了事件,所有点击触发后只会修改第一个li的样式。

可落地的实现方法

要实现任意li被点击时都能触发指定函数,有两种成熟的实现方式:

  1. 批量绑定独立监听器
    首先修正重复id的违规问题,给所有li设置统一的class标识,再通过批量选择器获取所有li,遍历绑定事件,回调中通过当前触发事件的节点操作样式:
    • 调整后的HTML代码
      <ul>
        <li class="todo-item">One</li>
        <li class="todo-item">Two</li>
        <li class="todo-item">Other</li>
      </ul>
      
    • 调整后的JS代码
      // 批量获取所有li元素
      const listItems = document.querySelectorAll(".todo-item");
      // 遍历每个元素绑定点击事件
      listItems.forEach(item => {
        item.addEventListener("click", clickTodo)
      })
      function clickTodo() {
        // this 指向当前被点击的触发元素
        this.style.color = "red"
      }
      
  2. 事件委托实现(适合动态列表场景)
    不需要给每个li单独绑定事件,将监听器挂载在父级ul上,利用事件冒泡机制判断点击目标,性能更高,也不会因为后续动态新增li丢失绑定效果:
    const todoList = document.querySelector("ul");
    todoList.addEventListener("click", (e) => {
      // 判断当前点击的目标是否为li元素
      if (e.target.tagName === "LI") {
        e.target.style.color = "red"
      }
    })
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.12 20:54:04