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

软页面跳转场景下JS类window事件监听器移除失败及作用域问题求助

问题根因
  • 第一版代码失效原因:resize事件绑定的是匿名箭头函数,没有把函数引用保存到实例属性,执行removeEventListener时没有传入对应要移除的函数引用,浏览器无法匹配到需要删除的监听器,操作自然不生效。
  • 第二版代码失效核心原因:类方法的this上下文绑定问题。如果你为了解决updateSwiper内部this指向错误的问题,在绑定时写了this.updateSwiper.bind(this),bind方法每次调用都会生成一个全新的函数实例,你没有把这个新生成的函数引用存下来,移除时传入的原始this.updateSwiper和绑定的函数不是同一个引用,浏览器无法匹配到对应监听器,所以移除失败。就算你没有主动bind,直接传this.updateSwiper,虽然移除逻辑本身是匹配的,但事件触发时updateSwiper内部的this会指向window,会出现this.swiper is undefined的运行错误,功能依然不正常。
修复方案

方案1:构造函数内提前绑定方法this

在构造函数里提前把updateSwiper的this绑定到实例,绑定和移除都用同一个实例属性的引用:

export default class Slider extends Core {
    constructor() {
        super();
        // 提前绑定this,绑定和移除都用这个绑定后的函数
        this.updateSwiper = this.updateSwiper.bind(this);
    }
    init() {
        this.swiper = new Swiper('.mySlider', {
            slidesOffsetBefore: this.sliderOffset(),
        });
        window.addEventListener('resize', this.updateSwiper);
    }

    updateSwiper() {
        this.swiper.params.slidesOffsetBefore = this.sliderOffset();
        this.swiper.update();
    }
    
    removeEventListeners() {
       window.removeEventListener('resize', this.updateSwiper);
    }

    sliderOffset() {
       // 执行相关逻辑后返回值
       return value
    }
}

方案2:类字段箭头函数(更简洁,适合现代JS/TS环境)

直接把updateSwiper定义为类的箭头函数字段,自动绑定this到实例,不需要额外bind:

export default class Slider extends Core {
    init() {
        this.swiper = new Swiper('.mySlider', {
            slidesOffsetBefore: this.sliderOffset(),
        });
        window.addEventListener('resize', this.updateSwiper);
    }

    // 箭头函数字段,this自动绑定到当前实例
    updateSwiper = () => {
        this.swiper.params.slidesOffsetBefore = this.sliderOffset();
        this.swiper.update();
    }
    
    removeEventListeners() {
       window.removeEventListener('resize', this.updateSwiper);
    }

    sliderOffset() {
       // 执行相关逻辑后返回值
       return value
    }
}

方案3:使用AbortController(无需维护函数引用,适合多监听器场景)

现代浏览器支持AbortController,可以统一管理多个监听器的销毁,不需要单独记每个函数的引用:

export default class Slider extends Core {
    init() {
        this.swiper = new Swiper('.mySlider', {
            slidesOffsetBefore: this.sliderOffset(),
        });
        // 初始化AbortController
        this.resizeAbortController = new AbortController();
        window.addEventListener('resize', () => {
            this.swiper.params.slidesOffsetBefore = this.sliderOffset();
            this.swiper.update();
        }, { signal: this.resizeAbortController.signal });
    }
    
    removeEventListeners() {
       // 直接触发abort即可移除所有绑定了对应signal的监听器
       this.resizeAbortController?.abort();
    }

    sliderOffset() {
       // 执行相关逻辑后返回值
       return value
    }
}

内容的提问来源于stack exchange,提问作者Albert de Beer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 07:27:04