Vue 3 过渡动画实战:用 Transition 与 TransitionGroup 做进出场和列表动画

test12026-09-241 次阅读

单元素进出场:Transition

Vue 内置的 <Transition> 组件会在元素插入、移除时自动切换一组 CSS 类(v-enter-from、v-enter-active、v-leave-to 等),不需要任何 JS 动画库。只要把需要做动画的元素包进 <Transition>,并用 v-if 控制显隐即可。

<template>
  <button @click="show = !show">切换</button>
  <Transition name="fade">
    <p v-if="show">一段会淡入淡出的文字</p>
  </Transition>
</template>

<script setup>
import { ref } from "vue";
const show = ref(true);
</script>

<style>
.fade-enter-active,
.fade-leave-active { transition: opacity 0.3s ease; }
.fade-enter-from,
.fade-leave-to { opacity: 0; }
</style>

name="fade" 决定了类名前缀,Vue 会自动拼接 enter-from、enter-active、enter-to 三阶段;leave 同理。想做位移就在对应类里写 transform。

列表动画:TransitionGroup

渲染 v-for 列表时,用 <TransitionGroup> 可以分别给"新增、删除、移动"的节点加动画,移动动画依靠 FLIP 技术实现,几乎零成本。注意它默认不会渲染包裹元素,需要指定 tag。

<template>
  <TransitionGroup name="list" tag="ul">
    <li v-for="item in items" :key="item.id">
      {{ item.text }}
      <button @click="remove(item.id)">删除</button>
    </li>
  </TransitionGroup>
</template>

<script setup>
import { ref } from "vue";
const items = ref([
  { id: 1, text: "任务一" },
  { id: 2, text: "任务二" },
]);
function remove(id: number) {
  items.value = items.value.filter((i) => i.id !== id);
}
</script>

<style>
.list-enter-active,
.list-leave-active { transition: all 0.3s ease; }
.list-enter-from,
.list-leave-to { opacity: 0; transform: translateX(20px); }
.list-move { transition: transform 0.3s ease; }
</style>

用 JS 钩子接管复杂动画

当 CSS 不够用时,Transition 支持 @before-enter、@enter、@leave 钩子,在里面调用 Web Animations API 或第三方动画库。钩子里调用 done() 告知 Vue 动画结束,避免提前移除节点。

<Transition @enter="onEnter" @leave="onLeave" :css="false">
  <div v-if="show" class="box">弹层</div>
</Transition>

<script setup>
function onEnter(el: Element, done: () => void) {
  (el as HTMLElement).animate(
    [{ transform: "scale(0.8)", opacity: 0 }, { transform: "scale(1)", opacity: 1 }],
    { duration: 250 }
  ).onfinish = done;
}
function onLeave(el: Element, done: () => void) {
  (el as HTMLElement).animate(
    [{ opacity: 1 }, { opacity: 0 }],
    { duration: 200 }
  ).onfinish = done;
}
</script>

实践要点

  • 列表动画必须给 v-for 的每一项加稳定且唯一的 key,否则移动动画会错乱。
  • 纯显隐用 CSS 类即可;需要物理动画或结合动画库时再用 JS 钩子,并设 :css="false" 关闭 CSS 检测。
  • 离开动画期间节点仍占位置,长列表频繁增删时留意性能,必要时对容器做 contain 优化。
T

test1

文章作者

单元素进出场:Transition Vue 内置的 <Transition> 组件会在元素插入、移除时自动切换一组 C...

分类
技术
发布时间
2026-09-24
字数
约 2407 字
阅读
1 次