如何正确销毁并重新初始化ScrollTrigger?(Nuxt+LocomotiveScroll场景)
Nuxt路由切换时LocomotiveScroll与GSAP ScrollTrigger冲突修复方案
你的判断完全正确,路由切换故障的核心原因是上一页的滚动相关实例、事件监听、代理配置没有被完全清理,导致新旧实例冲突。你更新后的代码方向正确,但仍有几处细节需要优化:
- 事件监听移除逻辑错误:
addEventListener和removeEventListener必须传入同一个函数引用,你两次使用独立的匿名箭头函数,无法匹配到已注册的监听,会导致事件重复触发、内存泄漏 - 未清理scrollerProxy:旧页面注册的
.js-scroll滚动代理没有被重置,新页面再次注册同选择器代理会产生冲突 - 未手动移除LocomotiveScroll的scroll事件监听:虽然LocomotiveScroll的destroy方法会清理自身事件,但手动提前解绑可以避免实例销毁延迟带来的残留问题
- 未兼容keep-alive缓存路由场景:如果你的Nuxt项目开启了路由缓存,还需要补充
activated/deactivated钩子的初始化和清理逻辑
修正后完整代码
export default { data() { return { lmS: null, refreshHandler: null // 存储refresh事件的引用,用于后续移除 }; }, mounted() { this.lmS = new this.locomotiveScroll({ el: document.querySelector(".js-scroll"), smooth: true, direction: "horizontal", lerp: 0.1, smartphone: { smooth: false, direction: "vertical" } }); // 存储事件处理函数的引用,保证添加和移除的是同一个函数 this.refreshHandler = () => this.lmS.update(); this.lmS.on("scroll", this.$ScrollTrigger.update); this.$ScrollTrigger.addEventListener("refresh", this.refreshHandler); const that = this; this.$ScrollTrigger.scrollerProxy(".js-scroll", { scrollTop(value) { return arguments.length ? that.lmS.scrollTo(value, 0, 0) : that.lmS.scroll.instance.scroll.y; }, scrollLeft(value) { return arguments.length ? that.lmS.scrollTo(value, 0, 0) : that.lmS.scroll.instance.scroll.x; }, getBoundingClientRect() { return { top: 0, left: 0, width: window.innerWidth, height: window.innerHeight }; }, pinType: document.querySelector(".js-scroll").style.transform ? "transform" : "fixed" }); this.$ScrollTrigger.refresh(true); }, // 如果开启了keep-alive路由缓存,取消注释使用这两个钩子 // activated() { // this.$ScrollTrigger.refresh(true) // this.lmS?.start() // }, // deactivated() { // this.lmS?.stop() // }, beforeDestroy() { // 移除当前页面所有ScrollTrigger实例 this.$ScrollTrigger.getAll().forEach(trigger => trigger.kill()); // 清理对应选择器的滚动代理 this.$ScrollTrigger.clearScrollProxy(".js-scroll"); // 移除注册的refresh事件 this.$ScrollTrigger.removeEventListener("refresh", this.refreshHandler); // 移除LocomotiveScroll绑定的scroll事件监听 this.lmS?.off("scroll", this.$ScrollTrigger.update); }, destroyed() { this.lmS?.destroy(); this.lmS = null; } };
内容的提问来源于stack exchange,提问作者P-at
相关产品推荐
相关产品推荐

