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

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));

关键说明

  1. 共享函数引用:handleTouchStart和handleTouchEnd现在是固定的全局函数,添加和移除监听时用的是同一个引用,确保removeEventListener能精准找到并移除目标监听。
  2. 分离变量更新:把尺寸相关变量的更新抽成单独函数,每次resize时仅更新这些变量,无需重新创建事件函数。
  3. 防抖优化:resize事件会随窗口拖动频繁触发,防抖能减少不必要的函数调用,提升页面性能。

内容的提问来源于stack exchange,提问作者Astw41

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 12:54:57