Vue3 TransitionGroup 组件:列表动画就这么简单

摘要:做后台管理系统的时候,经常要给列表加动画。商品列表、消息通知、标签页、看板卡片,这些东西加个动画,用户体验会好很多。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 有什么不一样

特性TransitionTransitionGroup
用途单个元素或组件一整个列表
渲染不渲染额外 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 动画这三个核心部分就可以了。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_13727