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

Nuxt3 Composition API下window.scroll仅触发一次如何解决

问题原因

代码存在两个核心错误,导致滚动事件无法持续触发:

  • <script setup> 是Composition API的编译语法糖,执行阶段不存在组件实例this,你写的this.handleScroll实际取值为undefined,并没有把定义好的滚动回调正确绑定到事件上,你看到的单次触发只是页面初始化时的偶发事件冒泡。
  • 直接在setup顶层判断process.client后绑定事件的时序不对,setup执行时DOM还未完成挂载,同时没有做组件卸载时的事件解绑,很容易出现绑定失效、内存泄漏问题。
正确实现方案

由于项目不启用SSR、构建静态站点,直接用Vue的客户端生命周期钩子绑定事件即可,不需要额外判断客户端环境:

<script setup>
import { onMounted, onBeforeUnmount } from 'vue'

const handleScroll = () => {
  console.log(window.scrollY)
}

onMounted(() => {
  // 直接引用作用域内的回调函数,不要加this
  // 配置passive: true做滚动性能优化,告知浏览器该回调不会阻止默认滚动行为
  window.addEventListener('scroll', handleScroll, { passive: true })
})

// 路由切换/组件卸载时移除监听,避免重复绑定和内存泄漏
onBeforeUnmount(() => {
  window.removeEventListener('scroll', handleScroll)
})
</script>

特殊情况处理

如果按上面写法绑定后仍然无法持续触发,说明当前页面的滚动容器不是window(Nuxt Content部分版本默认会给内容区设置独立滚动容器),直接替换绑定目标即可:

onMounted(() => {
  // 优先匹配Nuxt Content的内容容器,匹配不到再回退到window
  const scrollTarget = document.querySelector('.nuxt-content') || window
  scrollTarget.addEventListener('scroll', handleScroll, { passive: true })
})

onBeforeUnmount(() => {
  const scrollTarget = document.querySelector('.nuxt-content') || window
  scrollTarget.removeEventListener('scroll', handleScroll)
})

更简便的写法

Nuxt3内置了useWindowScroll组合式API,已经自动处理了客户端判断、事件绑定解绑、性能优化逻辑,直接使用可以减少手写代码的出错概率:

<script setup>
// y是响应式的纵向滚动距离,和window.pageYOffset返回值一致
const { y: pageYOffset } = useWindowScroll()

// 需要监听滚动值变化时直接用watch即可
watch(pageYOffset, (currentOffset) => {
  console.log(currentOffset)
})
</script>

如果已经在nuxt.config.ts中配置了ssr: false,所有和浏览器API、DOM相关的代码只要放在onMounted等客户端生命周期里,就不会出现构建报错,不需要额外写process.client判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:54:34