Vue3 TransitionGroup 组件:列表动画就这么简单
做后台管理系统的时候,经常要给列表加动画。商品列表、消息通知、标签页、看板卡片,这些东西加个动画,用户体验会好很多。Vue3 把 TransitionGroup 做成内置组件,就是为了解决这个问题。
为什么 Vue3 要把它做成内置组件
Vue2 时代要做列表动画,得找第三方库或者自己写复杂的 CSS 和 JS。Vue3 直接把它收进核心,原因有三个。
第一,列表太常见了。一个后台管理系统里,跟列表有关的组件占了四成以上。内置了就不用装依赖,拿来就能用。
第二,性能有保障。Vue 团队针对列表动画做了深度优化,数据变动大了也不卡。比社区方案更轻量也更稳。
第三,跟 Transition 用同一套规则。你会用 Transition 就会用 TransitionGroup,类名都一样,不用重新学。
核心用法:三步上手
第一步:用 TransitionGroup 包住列表
用 TransitionGroup 替换掉普通的容器。用 tag 指定要渲染成什么 HTML 标签,用 name 指定动画类名的前缀。
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</TransitionGroup>这里有个关键点:每个列表项必须绑唯一的 :key。Vue 要靠这个来识别每个元素,知道谁是谁,动画才能正常跑。
第二步:写好 CSS 动画
Vue 会自动加上这几个类名:
| 类名 | 什么时候触发 |
|---|---|
| .list-enter-from | 元素插入之前 |
| .list-enter-active | 元素插入过程中 |
| .list-enter-to | 元素插入完成 |
| .list-leave-from | 元素离开之前 |
| .list-leave-active | 元素离开过程中 |
| .list-leave-to | 元素离开完成 |
| .list-move | 元素位置变了 |
下面是一个完整的示例:
/* 进入动画 */
.list-enter-active {
transition: all 0.4s ease;
}
.list-enter-from {
opacity: 0;
transform: translateX(-30px);
}
/* 离开动画 */
.list-leave-active {
transition: all 0.4s ease;
position: absolute; /* 这个很关键,让离开的元素不占位置 */
}
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* 位置变化动画,这是 TransitionGroup 的核心 */
.list-move {
transition: transform 0.4s ease;
}离开动画里 position: absolute 这行很重要。如果不加,离开的元素还占着位置,其他元素移动的时候就会卡顿。
第三步:直接操作数组数据
加数据:
items.value.push({ id: Date.now(), name: "新项目" });删数据:
items.value.splice(index, 1);排序,会触发 move 动画:
items.value.sort((a, b) => a.priority - b.priority);跟 Transition 有什么不一样
| 特性 | Transition | TransitionGroup |
|---|---|---|
| 用途 | 单个元素或组件 | 一整个列表 |
| 渲染 | 不渲染额外 DOM | 默认渲染成 span,可以用 tag 改 |
| 模式 | 支持 in-out 和 out-in | 不支持 |
| 特殊类 | 没有 | 支持 move-class |
tag 属性的用法
默认情况下 TransitionGroup 会渲染成一个 <span>。你可以用 tag 改成别的标签。
<!-- 渲染成 ul -->
<TransitionGroup tag="ul" name="list">
<li v-for="item in items" :key="item.id">{{ item.text }}</li>
</TransitionGroup>
<!-- 渲染成 div -->
<TransitionGroup tag="div" name="grid" class="grid-container">
<div v-for="card in cards" :key="card.id">{{ card.title }}</div>
</TransitionGroup>move-class 是什么
当列表顺序变了的时候,元素需要平滑地移到新位置。Vue 会自动计算位置差异,你只需要定义好过渡效果就行。
/* 用默认命名 */
.list-move {
transition: transform 0.5s ease;
}如果想自定义类名,可以用 move-class:
<TransitionGroup name="list" move-class="custom-move">离开动画一定要设 position: absolute
为了让其他元素能平滑地移到离开元素的位置,离开的元素必须脱离文档流。
.list-leave-active {
position: absolute;
width: 100%; /* 保持宽度,避免布局抖动 */
}列表重新排序要注意 key
Vue 默认策略是就地更新。如果顺序变了,Vue 不会移动 DOM 元素,而是直接更新每个元素的内容。为了让 Vue 能认出每个元素,必须用唯一的 :key。
<!-- 正确:用唯一 id -->
<TransitionGroup name="list">
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</TransitionGroup>
<!-- 错误:用索引当 key -->
<TransitionGroup name="list">
<li v-for="(item, index) in items" :key="index">{{ item.name }}</li>
</TransitionGroup>用索引当 key 的话,Vue 分不清哪个是哪个,动画就会乱。
实际场景能做什么
一个演示项目里能看到这些场景:列表增删动画、排序动画、网格布局动画、标签页切换、消息通知队列、拖拽排序效果。
地址:https://gitee.com/benxiaohai1071/bxh-admin-vue3/tree/master/src/views/study/builtIncomponent/transitionGroup
总结
TransitionGroup 做三件事:用 tag 指定容器标签,用 name 指定动画前缀,用唯一的 key 标识每个元素。CSS 里记住进入动画、离开动画要加 absolute、以及 move 动画这三个核心部分就可以了。
本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!