Vue3的TransitionGroup与列表动画
在构建现代Web应用时,流畅、优雅的列表动画能极大提升用户体验。Vue3提供了专门的<TransitionGroup>组件来处理列表(如v-for渲染的项目)的增删和移动动画。本文将提供一份零基础、可立即上手的实战指南。
第一阶段:理解核心概念
<TransitionGroup> 是Vue内置的一个抽象组件,专门用于管理一组元素或组件(通常是列表)的进入、离开和移动过渡效果。它与普通的<Transition>组件不同,后者只管理单个元素的过渡。
它主要有三个核心作用:
- 为列表中的每个新元素应用进入动画。
- 为列表中被移除的元素应用离开动画。
- 为列表中位置发生变化的元素应用移动动画(通过FLIP技术实现平滑位移)。
核心属性:
tag:指定<TransitionGroup>渲染为哪个HTML元素标签。默认是<span>,但通常我们会设为<ul>或<div>。name:自动生成的过渡类名前缀。例如,设置name="fade"后,Vue会自动应用.fade-enter-active、.fade-leave-active等类名。css:是否使用CSS过渡。默认为true。若想使用JavaScript动画钩子,可设为false。mode:不适用于<TransitionGroup>。列表动画默认同时进行(先进后出)。
第二阶段:创建基础列表动画
本阶段将指导你创建一个带有淡入淡出和移动效果的简单列表。
-
搭建基础模板。在你的Vue组件中,准备一个数组数据源和一个用于添加新项目的输入框。
<template> <div> <input v-model="newItemText" @keyup.enter="addItem" placeholder="添加项目并回车" /> <!-- 过渡容器 --> <TransitionGroup name="list" tag="ul"> <li v-for="item in items" :key="item.id"> {{ item.text }} <button @click="removeItem(item.id)">×</button> </li> </TransitionGroup> </div> </template> -
编写对应的Script逻辑。定义
items数组和操作它的方法。<script setup> import { ref } from 'vue' const items = ref([ { id: 1, text: '项目 A' }, { id: 2, text: '项目 B' }, { id: 3, text: '项目 C' } ]) const newItemText = ref('') let nextId = 4 const addItem = () => { if (newItemText.value.trim()) { items.value.push({ id: nextId++, text: newItemText.value.trim() }) newItemText.value = '' } } const removeItem = (id) => { const index = items.value.findIndex(item => item.id === id) if (index !== -1) { items.value.splice(index, 1) } } </script> -
添加CSS过渡样式。这是实现动画的关键。创建以下CSS规则,定义从
.list-开头的类名对应的样式。/* 进入动画的初始状态和离开动画的结束状态 */ .list-enter-from, .list-leave-to { opacity: 0; transform: translateY(30px); } /* 进入动画的激活状态和离开动画的激活状态 */ .list-enter-active, .list-leave-active { transition: all 0.5s ease; } /* 移动动画的过渡 */ .list-move { transition: transform 0.5s ease; }关键点:
.list-enter-from:定义了元素开始进入时的起始状态。.list-enter-active:定义了元素进入过程中的过渡效果。.list-leave-active:定义了元素离开过程中的过渡效果。.list-leave-to:定义了元素离开结束时的最终状态。.list-move:用于处理列表项位置变化的动画,Vue会自动应用FLIP技术。
第三阶段:实现交错动画效果
为了让列表更生动,可以让每个项目的动画依次延迟发生,形成交错效果。这通常通过JavaScript钩子或动态内联样式实现。
-
使用JavaScript钩子。
<TransitionGroup>提供了@before-enter、@enter、@leave等钩子。利用@enter钩子,可以动态设置每个元素的延迟。<TransitionGroup name="staggered-fade" tag="ul" @before-enter="onBeforeEnter" @enter="onEnter" @leave="onLeave" > -
实现钩子函数。编写以下JavaScript函数来控制动画延迟。这里使用了一个库(如
velocity-animate)来执行动画,也可以使用纯CSS的transition-delay。// 假设引入了动画库 // import Velocity from 'velocity-animate' const onBeforeEnter = (el) => { el.style.opacity = 0 el.style.height = 0 } const onEnter = (el, done) => { // el.dataset.index 是我们在v-for中通过 :data-index="index" 传递的索引 const delay = el.dataset.index * 150 setTimeout(() => { // 使用动画库执行动画,完成后调用done Velocity( el, { opacity: 1, height: '1.6em' }, { complete: done } ) }, delay) } const onLeave = (el, done) => { const delay = el.dataset.index * 150 setTimeout(() => { Velocity( el, { opacity: 0, height: 0 }, { complete: done } ) }, delay) }同时,修改
v-for以传递索引::data-index="index"。 -
纯CSS交错方案。如果不想使用JS库,定义一个基于
transition-delay的CSS类,并通过内联样式动态设置--i变量。.staggered-fade-enter-active { transition: all 0.5s ease; transition-delay: calc(var(--i) * 100ms); }然后在模板中绑定样式:
:style="{'--i': index}"。
第四阶段:结合状态与动画(实用技巧)
-
动画与响应式状态同步。Vue的响应式系统保证了
items数组的变化会立即反映在DOM上,<TransitionGroup>则负责拦截这些变化并应用动画。因此,确保所有对items的修改都是通过其响应式代理方法(如push,splice)进行的。 -
处理初始列表渲染。默认情况下,列表初次渲染时项目没有进入动画。如果需要,添加
appear属性。<TransitionGroup name="list" tag="ul" appear> -
区分不同类型的动画。可以为进入和离开定义完全不同的动画效果。分别设置
.list-enter-active和.list-leave-active的样式。例如,进入时淡入并从左滑入,离开时淡出并向右滑出。 -
优化性能。对于长列表的移动动画,确保只为必要的CSS属性设置过渡。过多的属性(如
transform,opacity以外的属性)会触发昂贵的重绘和回流。
最后一步:将上述代码整合到你的Vue单文件组件(.vue文件)中,运行项目,尝试添加和删除列表项,观察动画效果。通过调整.list-*类中的transition属性值(如持续时间duration、缓动函数timing-function),以及交错动画中的延迟计算,你可以打造出符合你应用风格的独特列表动画。

暂无评论,快来抢沙发吧!