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

Vue项目中使用GSAP时无法获取scrollWidth属性值的问题

问题分析与解决

错误原因

你遇到的Cannot read properties of null (reading 'scrollWidth')报错,核心原因是代码执行时机不对:
在Vue组件中,DOM元素的渲染是异步的,你的GSAP初始化代码可能在组件DOM还没完全渲染完成时就执行了。这时section.querySelector(".oui")找不到对应元素,返回null,自然无法读取scrollWidth属性。而在原生HTML/CodePen环境中,脚本通常等待整个DOM加载完成后才运行,所以不会出现这个问题。

解决方案

要让GSAP代码在Vue组件DOM完全渲染后再执行,同时改用Vue推荐的方式获取DOM元素,避免直接操作全局DOM:

1. 把GSAP代码放到mounted钩子中

Vue的mounted钩子会在组件DOM渲染完成后触发,确保此时能获取到所有需要的元素。

2. 用Vue的ref替代document.querySelector

ref是Vue提供的安全获取组件内部DOM元素的方式,比直接查询全局DOM更可靠,尤其适合单页应用场景。

3. 给动态渲染元素加$nextTick(如果需要)

如果你的section是通过v-for动态生成的,需要等数据更新并完成DOM渲染后再执行GSAP代码,这时可以用this.$nextTick()包裹初始化逻辑。

4. 添加空值判断

在获取.oui元素后先判断是否存在,避免偶尔的渲染延迟导致报错。

修改后的代码示例

<template>
  <div ref="loaderContainer" class="loader">
    <span ref="loaderText" class="loader--text">0%</span>
  </div>
  
  <!-- 静态section或动态v-for生成的section,都可用ref获取 -->
  <section ref="sections" class="section-item" v-for="(item, idx) in sectionData" :key="idx">
    <div class="oui">{{ item.text }}</div>
  </section>
</template>

<script>
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import imagesLoaded from 'imagesloaded'

// 注册GSAP插件
gsap.registerPlugin(ScrollTrigger)

export default {
  data() {
    return {
      sectionData: [/* 你的section内容数据 */]
    }
  },
  mounted() {
    // 若为动态生成的section,用$nextTick确保DOM更新完成
    this.$nextTick(() => {
      this.initAnimation()
    })
  },
  methods: {
    initAnimation() {
      const images = gsap.utils.toArray('img')
      const loaderText = this.$refs.loaderText
      
      const updateProgress = (instance) => {
        loaderText.textContent = `${Math.round((instance.progressedCount * 100) / images.length)}%`
      }

      const showDemo = () => {
        document.body.style.overflow = 'auto'
        document.scrollingElement.scrollTo(0, 0)
        
        // 隐藏加载层
        gsap.to(this.$refs.loaderContainer, { autoAlpha: 0 })

        // 获取所有section元素
        const sections = this.$refs.sections
        sections.forEach((section, index) => {
          const ouiElement = section.querySelector('.oui')
          
          // 空值判断,避免报错
          if (!ouiElement) return
          
          const [xStart, xEnd] = index % 2 
            ? ['100%', (ouiElement.scrollWidth - section.offsetWidth) * -1]
            : [ouiElement.scrollWidth * -1, 0]
          
          gsap.fromTo(ouiElement, 
            { x: xStart },
            { 
              x: xEnd, 
              scrollTrigger: { 
                trigger: section, 
                scrub: 0.5 
              } 
            }
          )
        })
      }

      // 监听图片加载进度
      imagesLoaded(images).on('progress', updateProgress).on('always', showDemo)
    }
  }
}
</script>

额外注意事项

  • 确保已正确安装依赖包:
    npm install gsap imagesloaded
    
  • 如果section是静态写在模板里的(没用v-for),可以直接用this.$el.querySelectorAll('section')获取,不需要ref。
  • 测试时可在initAnimation开头打印console.log(this.$refs.sections),确认是否能正确获取DOM元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:53:20