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

JavaScript如何仅添加一个事件监听器 重复绑定问题排查

问题根源
  • 你每次调用MyLib.init()时,都会在init方法内部创建一个全新的doSomthing函数实例。removeEventListener生效的前提是,传入的处理函数引用和当初addEventListener绑定时的引用完全一致,两次init生成的函数是完全独立的两个对象,所以移除操作不会生效,每次调用都会新增一个点击监听器。
  • 同时你的doSomthing依赖传入的data参数,直接把函数固定在全局作用域还要考虑参数更新的适配问题。
解决方法

你可以把事件处理函数的引用存在mylib的顶层闭包中,每次init时先判断有没有已经绑定的处理函数,先移除旧的再绑定新的,示例修正代码如下:

"use strict";
const MyLib = mylib();
function mylib() {
  // 顶层闭包存储已绑定的处理函数引用
  let boundHandler = null;
  const res = {
    init:(data) => {
        const btn = document.getElementById('my-btn');
        // 先移除之前绑定的处理函数
        if (boundHandler) {
          console.log('REMOVING EVENT LISTENER')
          btn.removeEventListener('click', boundHandler, false);
        }
        // 生成新的处理函数
        const doSomthing = () => {
         console.log('somthing', data)
        }
        // 存储新的处理函数引用
        boundHandler = doSomthing;
        console.log('ADDING EVENT LISTENER')
        btn.addEventListener('click', boundHandler, false);
    }
  };
  return res;
}

如果你的场景不需要每次init都更新doSomthing依赖的data,也可以直接把doSomthing定义在init方法外层,只初始化一次,每次init只执行一次移除逻辑避免重复绑定即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 09:15:03