🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx skills add https://skills.sh/greensock/gsap-skills/gsap-frameworks

💡 提示:需要 Node.js 和 NPM

GSAP 与 Vue、Svelte 及其他框架

何时使用此技能

在编写或审阅 Vue(或 Nuxt)、Svelte(或 SvelteKit)或其他使用生命周期(挂载/卸载)的组件框架中的 GSAP 代码时使用此技能。对于React,请专门使用 gsap-react(useGSAP 钩子,gsap.context())。

相关技能: 对于补间和动画时间线,请使用 gsap-coregsap-timeline;对于基于滚动的动画,请使用 gsap-scrolltrigger;对于 React,请使用 gsap-react

原则(所有框架)

  • 创建补间和滚动触发器组件的 DOM 可用之后(例如 onMounted, onMount)。
  • 卸载(或等效操作)中销毁或恢复它们,以确保没有动画在已分离的节点上运行,并避免内存泄漏。
  • 将选择器限定在组件根元素范围内,这样 .box 和类似的类名只匹配该组件内部的元素,而不会影响页面其他部分。

Vue 3(组合式 API)

使用 onMounted 在组件挂载到 DOM 后运行 GSAP。使用 onUnmounted 进行清理。

import { onMounted, onUnmounted, ref } from "vue";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger); // 在每个应用中注册一次,例如在 main.js 中

export default {
  setup() {
    const container = ref(null);
    let ctx;

    onMounted(() => {
      if (!container.value) return;
      ctx = gsap.context(() => {
        gsap.to(".box", { x: 100, duration: 0.6 });
        gsap.from(".item", { autoAlpha: 0, y: 20, stagger: 0.1 });
      }, container.value);
    });

    onUnmounted(() => {
      ctx?.revert();
    });

    return { container };
  }
};
  • gsap.context(scope) — 将容器引用(例如 container.value)作为第二个参数传入,以便像 .item 这样的选择器被限定在该根元素内。在回调中创建的所有动画和滚动触发器都会被跟踪,并在调用 ctx.revert() 时恢复。
  • onUnmounted — 始终调用 ctx.revert(),以便补间和滚动触发器被终止,内联样式被恢复。

Vue 3(script setup)

使用 <script setup> 和 ref 的相同思路:

<script setup>
import { onMounted, onUnmounted, ref } from "vue";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

const container = ref(null);
let ctx;

onMounted(() => {
  if (!container.value) return;
  ctx = gsap.context(() => {
    gsap.to(".box", { x: 100 });
    gsap.from(".item", { autoAlpha: 0, stagger: 0.1 });
  }, container.value);
});

onUnmounted(() => {
  ctx?.revert();
});
</script>

<template>
  <div ref="container">
    <div class="box">Box</div>
    <div class="item">Item</div>
  </div>
</template>

Svelte

使用 onMount 在 DOM 准备就绪后运行 GSAP。使用 onMount 返回的清理函数(或跟踪上下文并在响应式块/组件销毁中清理)进行恢复。Svelte 5 使用不同的生命周期;相同的原则适用:在“挂载”时创建,在“销毁”时恢复。

<script>
  import { onMount } from "svelte";
  import { gsap } from "gsap";
  import { ScrollTrigger } from "gsap/ScrollTrigger";

  let container;

  onMount(() => {
    if (!container) return;
    const ctx = gsap.context(() => {
      gsap.to(".box", { x: 100 });
      gsap.from(".item", { autoAlpha: 0, stagger: 0.1 });
    }, container);
    return () => ctx.revert();
  });
</script>

<div bind:this={container}>
  <div class="box">Box</div>
  <div class="item">Item</div>
</div>
  • bind:this={container} — 获取对根元素的引用,以便将其传递给 gsap.context(scope)
  • return () => ctx.revert() — Svelte 的 onMount 可以返回一个清理函数;在此处调用 ctx.revert(),以便在组件被销毁时运行清理。

选择器限定范围

不要使用可能匹配当前组件外部元素的全局选择器。始终将作用域(容器元素或引用)作为第二个参数传递给 gsap.context(callback, scope),以便在回调内部运行的任何选择器都被限制在该子树内。

  • gsap.context(() => { gsap.to(“.box”, …) }, containerRef).box 仅在 containerRef 内部搜索。
  • ❌ 在组件中不带上下文作用域运行 gsap.to(“.box”, …) 可能会影响其他实例或页面的其余部分。

滚动触发器清理

当您在补间/时间线或 ScrollTrigger.create() 上使用 scrollTrigger 配置时,会创建滚动触发器实例。它们包含在 gsap.context() 中,并在您调用 ctx.revert() 时被恢复。因此:

  • 在与补间相同的 gsap.context() 回调中创建滚动触发器。
  • 在影响触发器位置的布局更改后(例如在数据加载后),调用 ScrollTrigger.refresh();在 Vue/Svelte 中,这通常意味着在 DOM 更新之后(例如 Vue 中的 nextTick,Svelte 中的 tick,或在异步内容加载之后)。

何时创建与销毁

生命周期 操作
挂载时 gsap.context(scope) 内部创建补间和滚动触发器。
卸载 / 销毁时 调用 ctx.revert(),以便该上下文中的所有动画和滚动触发器都被终止,并且内联样式被恢复。

不要在组件的 setup 或根元素存在之前运行的同步顶级脚本中创建 GSAP 动画。等待 onMounted / onMount(或等效操作),以便容器引用存在于 DOM 中。

禁止事项

  • ❌ 在组件挂载之前创建补间或滚动触发器(例如在 setup 中而没有 onMounted);DOM 节点可能尚不存在。
  • ❌ 使用不带作用域的选择器字符串(将容器作为第二个参数传递给 gsap.context()),以免选择器匹配到组件外部的元素。
  • ❌ 跳过清理;始终在 onUnmounted / onMount 的返回中调用 ctx.revert(),以便在组件被销毁时终止动画和滚动触发器。
  • ❌ 在每次渲染都会运行的组件体内注册插件(虽然不会造成损害,但很浪费);在应用级别注册一次。

了解更多

  • gsap-react 技能,了解 React 特定的模式(useGSAP,contextSafe)。

📄 原始文档

完整文档(英文):

https://skills.sh/greensock/gsap-skills/gsap-frameworks

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。