无法移除事件监听:Todo应用保存按钮事件监听堆积问题
解决Todo模态框保存按钮事件监听堆积问题
问题根源
每次调用bind()都会生成一个全新的函数实例,你添加监听时用的是bind()返回的新函数,但移除时传入的todoManager.createTodo.bind(甚至这都不是正确的绑定调用)和之前添加的函数完全不匹配,导致移除操作无效,监听不断堆积,最终重复触发操作。
另外你原来的编辑监听写法有问题:() => todoManager.editTodo.bind(caller.id)只是返回了一个绑定后的函数,并没有执行editTodo,点击按钮实际不会触发编辑逻辑,正确写法应该是() => todoManager.editTodo(caller.id)或者todoManager.editTodo.bind(todoManager, caller.id)(绑定上下文和参数)。
两种可行解决方案
方案一:维护绑定函数的引用,统一添加/移除
在模块中保存每次绑定后的函数引用,切换操作(新建/编辑)时先移除上一次的监听,再添加新的:
// 模块级变量,保存当前的保存按钮监听函数 let currentSaveHandler = null; const saveBtn = getDom().todoModalSaveBtn; // 打开新建模态框的逻辑 function openCreateModal() { // 先移除上一次的监听 if (currentSaveHandler) { saveBtn.removeEventListener('click', currentSaveHandler); } // 创建绑定后的新建函数并保存引用 currentSaveHandler = todoManager.createTodo.bind(todoManager); // 添加新监听 saveBtn.addEventListener('click', currentSaveHandler); // 清空表单、打开模态框... } // 打开编辑模态框的逻辑 function openEditModal(caller) { // 先移除上一次的监听 if (currentSaveHandler) { saveBtn.removeEventListener('click', currentSaveHandler); } // 创建绑定后的编辑函数(绑定上下文和todoId参数)并保存引用 currentSaveHandler = todoManager.editTodo.bind(todoManager, caller.id); // 添加新监听 saveBtn.addEventListener('click', currentSaveHandler); // 填充表单数据、打开模态框... }
方案二:只添加一次监听,通过模态框数据判断操作类型
更简洁的方式是给按钮只绑定一次监听,通过模态框的自定义属性标记当前是新建还是编辑,以及对应的Todo ID:
const saveBtn = getDom().todoModalSaveBtn; const todoModal = getDom().todoModal; // 只添加一次监听,后续不再重复绑定 saveBtn.addEventListener('click', handleSave); // 打开新建模态框 function openCreateModal() { todoModal.dataset.action = 'create'; // 清空表单、打开模态框... } // 打开编辑模态框 function openEditModal(caller) { todoModal.dataset.action = 'edit'; todoModal.dataset.todoId = caller.id; // 填充表单数据、打开模态框... } // 统一的保存处理逻辑 function handleSave() { const action = todoModal.dataset.action; if (action === 'create') { todoManager.createTodo(); } else if (action === 'edit') { const todoId = todoModal.dataset.todoId; todoManager.editTodo(todoId); } // 关闭模态框、清理数据... }
这种方式从根源避免了监听堆积,逻辑更清晰,也不需要频繁添加/移除监听。
内容的提问来源于stack exchange,提问作者maverickar
相关产品推荐
相关产品推荐

