Nuxt.js中overflow:hidden固定定位元素如何监听scroll事件
问题根因
- 原生
scroll事件只有在元素自身产生滚动上下文(即内容溢出、出现可交互滚动条)时才会触发,你给#test设置了overflow:hidden后,溢出内容会被直接裁剪,元素本身不会产生任何滚动行为,绑定的scroll监听自然永远不会触发。 - 你贴的代码里存在语法错误:
const t = = document.getElementById('test')多写了一个等号,运行时会直接抛出语法错误,阻断后续逻辑执行。
不要依赖原生scroll事件,直接监听用户的滚动输入行为(鼠标滚轮、移动端触摸滑动),自行维护滚动位置参数来驱动表单动画即可,不需要改动现有样式规则。
实现代码
模板部分保持原有结构即可,脚本部分修正语法错误后替换事件监听逻辑,注意Nuxt环境下要确保DOM操作仅在客户端执行:
<script setup lang="ts"> import { ref, onMounted, onBeforeUnmount } from 'vue' // 自定义滚动进度值,用于驱动表单动画 const scrollProgress = ref(0) // 可根据业务调整的配置项 const config = { wheelStep: 30, // 鼠标滚轮单次滚动步长 maxScroll: 500, // 最大可滚动距离,匹配动画需要的行程 animationTriggerPoint: 200 // 触发表单入场动画的滚动阈值 } // 鼠标滚轮事件处理 const handleWheel = (e: WheelEvent) => { e.preventDefault() const step = e.deltaY > 0 ? config.wheelStep : -config.wheelStep scrollProgress.value = Math.max(0, Math.min(config.maxScroll, scrollProgress.value + step)) triggerFormAnimation() } // 移动端触摸滑动事件处理 let touchStartY = 0 const handleTouchStart = (e: TouchEvent) => { touchStartY = e.touches[0].clientY } const handleTouchMove = (e: TouchEvent) => { e.preventDefault() const currentY = e.touches[0].clientY const delta = touchStartY - currentY touchStartY = currentY scrollProgress.value = Math.max(0, Math.min(config.maxScroll, scrollProgress.value + delta)) triggerFormAnimation() } // 表单动画触发逻辑 const triggerFormAnimation = () => { console.log('当前滚动进度:', scrollProgress.value) if (scrollProgress.value >= config.animationTriggerPoint) { // 此处编写表单入场动画逻辑,比如添加动态类名、修改CSS变量控制transform/opacity } } onMounted(() => { const testEl = document.getElementById('test') if (!testEl) return // 绑定滚轮、触摸事件,passive设为false才能正常阻止默认滚动行为 testEl.addEventListener('wheel', handleWheel, { passive: false }) testEl.addEventListener('touchstart', handleTouchStart, { passive: false }) testEl.addEventListener('touchmove', handleTouchMove, { passive: false }) }) onBeforeUnmount(() => { const testEl = document.getElementById('test') if (!testEl) return // 移除事件监听避免内存泄漏 testEl.removeEventListener('wheel', handleWheel) testEl.removeEventListener('touchstart', handleTouchStart) testEl.removeEventListener('touchmove', handleTouchMove) }) </script>
优化建议
- 如果你用的
<full-page>是vue-fullpage类的全屏滚动组件,可以直接调用组件自带的afterLoad、onLeave等滚动回调钩子,基于当前屏索引触发动画,和组件逻辑适配度更高。 - 做动画时优先把
scrollProgress的值绑定为CSS变量,直接在CSS中通过transform、opacity属性实现动画,比手动操作DOM性能更好。 - 如果需要更顺滑的滚动体验,可以给
scrollProgress加过渡效果,避免滚轮触发时动画跳变。
内容的提问来源于stack exchange,提问作者HNG
相关产品推荐
相关产品推荐

