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

removeEventListener失效问题:绑定的点击事件无法单次触发如何解决?

问题分析与解决方案

你的问题根源有两个:

  • 循环内定义的命名函数表达式,每次循环都会生成全新的函数实例,导致removeEventListener找不到对应的函数引用,自然无法移除监听器。
  • makeAllyTargets每次调用都会往ally_targets数组重复添加元素,多次触发Angels_Grace会让同一个角色被绑定多组监听器,加剧重复触发的问题。

最优解决方案:利用once自动移除监听器

直接使用addEventListener的once配置项,让监听器触发一次后自动销毁,无需手动调用移除方法,代码更简洁可靠:

var ally_targets = []

// 修复:每次生成目标前清空数组,避免重复添加元素
function makeAllyTargets() {
  ally_targets = []
  let maketargets = document.getElementsByClassName('ally_img')
  for (let i = 0; i < maketargets.length; i++) {
    ally_targets.push(maketargets[i])
  }
}

var amt_healed

function Angels_Grace() { // 单体中等治疗法术
  makeAllyTargets()
  for (let i = 0; i < ally_targets.length; i++) {
    ally_targets[i].addEventListener('click', function() {
      const selected_ally = ally_targets.indexOf(this)
      switch (selected_ally) {
        case 0: // 骑士
          amt_healed = 303
          // 确保治疗不超过生命值上限
          const currentHp = parseInt(warrior_hp.value)
          if (currentHp + amt_healed > 550) {
            Angels_Grace_Part2()
            warrior_hp.value = 550
          } else {
            Angels_Grace_Part2()
            warrior_hp.value = currentHp + amt_healed
          }
          break
        // 其他角色的case逻辑保持不变
        default:
          console.log("治疗switch逻辑异常")
          break
      }
    }, { once: true }) // 关键配置:监听器仅触发一次后自动移除
  }
}

兼容旧环境的方案:手动管理函数引用

如果需要兼容不支持once选项的旧浏览器,可以把处理函数提取到循环内,用闭包保存唯一引用,确保能正确移除:

var ally_targets = []

function makeAllyTargets() {
  ally_targets = []
  let maketargets = document.getElementsByClassName('ally_img')
  for (let i = 0; i < maketargets.length; i++) {
    ally_targets.push(maketargets[i])
  }
}

var amt_healed

function Angels_Grace() {
  makeAllyTargets()
  for (let i = 0; i < ally_targets.length; i++) {
    // 为每个元素创建独立的处理函数
    const handleHealClick = function() {
      const selected_ally = ally_targets.indexOf(this)
      switch (selected_ally) {
        case 0: // 骑士
          amt_healed = 303
          const currentHp = parseInt(warrior_hp.value)
          if (currentHp + amt_healed > 550) {
            Angels_Grace_Part2()
            warrior_hp.value = 550
          } else {
            Angels_Grace_Part2()
            warrior_hp.value = currentHp + amt_healed
          }
          // 现在可以正确移除,因为handleHealClick是当前元素绑定的唯一函数引用
          this.removeEventListener('click', handleHealClick)
          break
        // 其他角色的case逻辑保持不变
        default:
          console.log("治疗switch逻辑异常")
          break
      }
    }
    ally_targets[i].addEventListener('click', handleHealClick)
  }
}

额外注意事项

  • 务必修复makeAllyTargets的数组清空逻辑,否则每次调用Angels_Grace都会重复添加元素,导致同一个角色被绑定多组监听器。
  • warrior_hp.value默认是字符串类型,需要用parseInt转成数字后再计算,避免出现字符串拼接的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 11:50:20