touchstart与touchend事件监听未移除问题的修复咨询
修复滑动关闭功能在窗口 resize 后的事件监听问题
问题根源
你遇到的核心问题是:每次调用swipeClose()时,都会在函数内部重新创建handleTouchStart和handleTouchEnd这两个函数。这意味着添加监听时用的函数引用,和移除监听时传入的函数引用不是同一个,所以removeEventListener根本找不到要移除的监听,导致大窗口下滑动手势依然生效。
修复方案
把事件处理函数、触摸状态变量以及依赖窗口尺寸的变量移到swipeClose函数外部,保证所有操作共享同一个函数引用;同时在窗口resize时仅更新尺寸相关变量,根据当前窗口宽度决定添加/移除监听。另外可以给resize事件加防抖,避免频繁触发。
修改后的完整代码
// 全局共享的触摸状态变量 let touchStartX = null; let touchStartY = null; let touchEndX = null; let touchEndY = null; // 依赖窗口尺寸的变量,初始值在首次调用时设置 let minSwipeWidth; let maxSwipeHeight; let swipeStartPoint; let swipeEndPoint; let swipeRightStartPoint; let swipeRightEndPoint; // 目标元素和类名(需确保你已提前定义这两个变量) const scContainer = /* 你的目标DOM元素 */; const scOpen = /* 要移除的类名 */; // 共享的事件处理函数 function handleTouchStart(e){ touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; } function handleTouchEnd(e){ touchEndX = e.changedTouches[0].clientX; touchEndY = e.changedTouches[0].clientY; const swipeWidth = Math.abs(touchEndX - touchStartX); const swipeHeight = Math.abs(touchEndY - touchStartY); // 检查滑动条件 if (swipeWidth >= minSwipeWidth && swipeHeight <= maxSwipeHeight) { if ( (touchStartX >= swipeStartPoint && touchStartX <= swipeEndPoint) || (touchStartX <= swipeRightStartPoint && touchStartX >= swipeRightEndPoint) ) { scContainer.removeClass(scOpen); } } // 重置触摸状态 touchStartX = null; touchStartY = null; touchEndX = null; touchEndY = null; } // 更新尺寸相关变量的函数 function updateSwipeDimensions() { minSwipeWidth = window.innerWidth * 0.45; maxSwipeHeight = window.innerHeight * 0.15; swipeStartPoint = window.innerWidth * 0.05; swipeEndPoint = window.innerWidth * 0.35; swipeRightStartPoint = window.innerWidth - swipeStartPoint; swipeRightEndPoint = window.innerWidth - swipeEndPoint; } // 核心逻辑函数 function swipeClose(){ updateSwipeDimensions(); if (window.innerWidth <= 1024) { document.addEventListener("touchstart", handleTouchStart); document.addEventListener("touchend", handleTouchEnd); } else { // 移除监听,此时函数引用和添加时完全一致 document.removeEventListener("touchstart", handleTouchStart); document.removeEventListener("touchend", handleTouchEnd); } } // 防抖函数,避免resize频繁触发 function debounce(func, delay = 200) { let timeoutId; return function() { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, arguments), delay); }; } // 初始化和绑定resize事件 swipeClose(); window.addEventListener("resize", debounce(swipeClose));
关键说明
- 共享函数引用:
handleTouchStart和handleTouchEnd现在是固定的全局函数,添加和移除监听时用的是同一个引用,确保removeEventListener能精准找到并移除目标监听。 - 分离变量更新:把尺寸相关变量的更新抽成单独函数,每次resize时仅更新这些变量,无需重新创建事件函数。
- 防抖优化:resize事件会随窗口拖动频繁触发,防抖能减少不必要的函数调用,提升页面性能。
内容的提问来源于stack exchange,提问作者Astw41
相关产品推荐
相关产品推荐

