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
相关产品推荐
相关产品推荐

