如何移除需传递多参数的JavaScript触摸事件监听器
解决无法移除触摸事件监听器的问题
问题根源:用箭头函数包裹回调传递额外参数时,每次addEventListener都会创建新的函数引用,而removeEventListener必须使用和添加时完全一致的函数才能生效,直接用原函数名自然无法移除。
下面给出两种可行的解决方式:
方法一:保存包装后的函数引用
把每个箭头函数的引用存储在元素的自定义属性中,移除时直接调用这些引用即可:
修改后的核心代码
function addCloseEventListeners(swipeTab) { // 先移除已存在的监听器,避免重复绑定 if (swipeTab._eventHandlers) { removeCloseEventListeners(swipeTab); } // 创建并保存包装后的事件处理函数 const startHandler = e => closeStart(e); const moveHandler = e => closeMove(e, swipeTab); const endHandler = e => closeEnd(e, swipeTab); swipeTab._eventHandlers = { startHandler, moveHandler, endHandler }; // 添加监听器 swipeTab.addEventListener('touchstart', startHandler); swipeTab.addEventListener('touchmove', moveHandler); swipeTab.addEventListener('touchend', endHandler); } function removeCloseEventListeners(swipeTab) { if (!swipeTab._eventHandlers) return; const { startHandler, moveHandler, endHandler } = swipeTab._eventHandlers; // 移除监听器 swipeTab.removeEventListener('touchstart', startHandler); swipeTab.removeEventListener('touchmove', moveHandler); swipeTab.removeEventListener('touchend', endHandler); // 清理存储的引用 delete swipeTab._eventHandlers; } // 修复closeTab中的参数错误 function closeTab(swipeTab) { swipeTab.style.transition = `all 0.2s ease-in-out`; swipeTab.style.transform = `translate3d(0, 100%, 0)`; removeCloseEventListeners(swipeTab); // 原代码此处参数错误,已修正 }
方法二:利用事件委托(适配动态插入元素)
如果标签页是动态插入DOM的,可以把监听器绑定到一个固定存在的父元素上,通过事件冒泡判断目标元素,无需手动绑定/移除监听器,仅通过类名控制事件是否生效:
示例代码
// 假设父容器是.tabs-container,页面加载时已存在 const tabContainer = document.querySelector('.tabs-container'); // 统一绑定触摸事件到父容器 tabContainer.addEventListener('touchstart', e => { const swipeTab = e.target.closest('.swipeable-tab'); // 只处理处于打开状态的标签页 if (!swipeTab || !swipeTab.classList.contains('open')) return; closeStart(e); }); tabContainer.addEventListener('touchmove', e => { const swipeTab = e.target.closest('.swipeable-tab'); if (!swipeTab || !swipeTab.classList.contains('open')) return; closeMove(e, swipeTab); }); tabContainer.addEventListener('touchend', e => { const swipeTab = e.target.closest('.swipeable-tab'); if (!swipeTab || !swipeTab.classList.contains('open')) return; closeEnd(e, swipeTab); }); // 修改openTab和closeTab,通过类名标记状态 function openTab(swipeTab) { swipeTab.style.transition = `all 0.2s ease-in-out`; swipeTab.style.transform = `translate3d(0, 0%, 0)`; swipeTab.classList.add('open'); } function closeTab(swipeTab) { swipeTab.style.transition = `all 0.2s ease-in-out`; swipeTab.style.transform = `translate3d(0, 100%, 0)`; swipeTab.classList.remove('open'); }
这种方式无需管理监听器的绑定与移除,仅通过open类名控制事件逻辑,更适合动态元素场景。
内容的提问来源于stack exchange,提问作者dbzx10299
相关产品推荐
相关产品推荐

