Vue3/Nuxt3如何捕获滚动位置?window.scrollY报错原因
问题描述
尝试在滚动到特定位置时改变导航栏颜色,但使用window.scrollY触发了错误。
相关代码
const navBar = computed<NavigationBarData>( () => { if (window.scrollY < 100) { return { secondaryNavColor: 'transparent', primaryNavColor: 'transparent', } } else { return { secondaryNavColor: 'gray-lighten-3', primaryNavColor: 'surface', } } } )
错误信息
500 Cannot read properties of undefined (reading 'scrollY')
原因分析
Nuxt3默认启用服务端渲染(SSR)。服务端执行代码时,不存在window对象(这是浏览器特有的全局对象),因此computed属性在服务端初始化时访问window.scrollY,会直接抛出"window is undefined"的错误。
解决方案
方案1:使用Nuxt内置的useWindowScroll(推荐)
Nuxt3提供了专门的组合式函数useWindowScroll,自动处理SSR环境,安全监听滚动位置:
const { y: scrollY } = useWindowScroll() const navBar = computed<NavigationBarData>(() => { return scrollY.value < 100 ? { secondaryNavColor: 'transparent', primaryNavColor: 'transparent' } : { secondaryNavColor: 'gray-lighten-3', primaryNavColor: 'surface' } })
方案2:手动判断环境并监听滚动事件
如果需要自定义实现,可先判断是否处于浏览器环境,再通过事件监听更新滚动位置:
const scrollY = ref(0) if (process.client) { // 初始化当前滚动位置 scrollY.value = window.scrollY // 监听滚动事件更新位置 const updateScroll = () => { scrollY.value = window.scrollY } window.addEventListener('scroll', updateScroll) // 组件卸载时移除监听 onUnmounted(() => { window.removeEventListener('scroll', updateScroll) }) } const navBar = computed<NavigationBarData>(() => { return scrollY.value < 100 ? { secondaryNavColor: 'transparent', primaryNavColor: 'transparent' } : { secondaryNavColor: 'gray-lighten-3', primaryNavColor: 'surface' } })
方案3:在onMounted中处理逻辑
onMounted钩子仅在浏览器端执行,可将依赖window的逻辑放在这里:
const navBar = ref<NavigationBarData>({ secondaryNavColor: 'transparent', primaryNavColor: 'transparent' }) onMounted(() => { const updateNavColors = () => { navBar.value = window.scrollY < 100 ? { secondaryNavColor: 'transparent', primaryNavColor: 'transparent' } : { secondaryNavColor: 'gray-lighten-3', primaryNavColor: 'surface' } } // 初始化颜色 updateNavColors() // 添加滚动监听 window.addEventListener('scroll', updateNavColors) // 清理监听 onUnmounted(() => { window.removeEventListener('scroll', updateNavColors) }) })
内容的提问来源于stack exchange,提问作者Qiuzman
相关产品推荐
相关产品推荐

