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
相关产品推荐
相关产品推荐

