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

Nuxt.js中overflow:hidden固定定位元素如何监听scroll事件

问题根因
  • 原生scroll事件只有在元素自身产生滚动上下文(即内容溢出、出现可交互滚动条)时才会触发,你给#test设置了overflow:hidden后,溢出内容会被直接裁剪,元素本身不会产生任何滚动行为,绑定的scroll监听自然永远不会触发。
  • 你贴的代码里存在语法错误:const t = = document.getElementById('test')多写了一个等号,运行时会直接抛出语法错误,阻断后续逻辑执行。
可行方案(满足保留overflow:hidden、其余元素固定定位的约束)

不要依赖原生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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:09:21