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

如何移除需传递多参数的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 20:55:20