<Transition> <TransitionGroup>
Vue 提供了两个内置组件,可以制作基于状态变化的过渡和动画:
-
<Transition>会在一个元素或组件进入和离开 DOM 时应用动画。 -
<TransitionGroup>会在一个v-for列表中的元素或组件被插入,移动,或移除时应用动画。
<Transition> 组件
<Transition> 是一个内置组件,这意味着它在任意别的组件中都可以被使用,无需注册。它可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。进入或离开可以由以下的条件之一触发:
- 由
v-if所触发的切换 - 由
v-show所触发的切换 - 由特殊元素
<component>切换的动态组件 - 改变特殊的
key属性
CSS 过渡 class
一共有 6 个应用于进入与离开过渡效果的 CSS class。

-
v-enter-from:进入动画的起始状态。在元素插入之前添加,在元素插入完成后的下一帧移除。 -
v-enter-active:进入动画的生效状态。应用于整个进入动画阶段。在元素被插入之前添加,在过渡或动画完成之后移除。这个 class 可以被用来定义进入动画的持续时间、延迟与速度曲线类型。 -
v-enter-to:进入动画的结束状态。在元素插入完成后的下一帧被添加 (也就是v-enter-from被移除的同时),在过渡或动画完成之后移除。 -
v-leave-from:离开动画的起始状态。在离开过渡效果被触发时立即添加,在一帧后被移除。 -
v-leave-active:离开动画的生效状态。应用于整个离开动画阶段。在离开过渡效果被触发时立即添加,在过渡或动画完成之后移除。这个 class 可以被用来定义离开动画的持续时间、延迟与速度曲线类型。 -
v-leave-to:离开动画的结束状态。在一个离开动画被触发后的下一帧被添加 (也就是v-leave-from被移除的同时),在过渡或动画完成之后移除。
TransitionGroup
<TransitionGroup> 是一个内置组件,用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果。
和 <Transition> 的区别
<TransitionGroup> 支持和 <Transition> 基本相同的 props、CSS 过渡 class 和 JavaScript 钩子监听器,但有以下几点区别:
-
默认情况下,它不会渲染一个容器元素。但你可以通过传入
tagprop 来指定一个元素作为容器元素来渲染。 -
过渡模式在这里不可用,因为我们不再是在互斥的元素之间进行切换。
-
列表中的每个元素都必须有一个独一无二的
keyattribute。 -
CSS 过渡 class 会被应用在列表内的元素上,而不是容器元素上。
<template>
<span>
<button @click="show = !show">Toggle</button>
<Transition>
<p v-if="show">hello</p>
</Transition>
<Transition name="slide-fade">
<p v-if="show">hello</p>
</Transition>
<button @click="insert">insert at random index</button>
<button @click="reset">reset</button>
<button @click="shuffle">shuffle</button>
<TransitionGroup tag="ul" name="fade" class="container">
<div v-for="item in items" class="item" :key="item">
{{ item }}
<button @click="remove(item)">x</button>
</div>
</TransitionGroup>
</span>
</template>
<script>
import {
shuffle as _shuffle
} from 'lodash-es'
export default {
data() {
return {
show: true,
items: [1, 2, 3, 4, 5]
}
},
methods: {
insert() {
const i = Math.round(Math.random() * this.items.length)
let id = this.items.length + 1
this.items.splice(i, 0, id++)
},
reset() {
this.items = [1, 2, 3, 4, 5]
},
shuffle() {
this.items = _shuffle(this.items)
},
remove(item) {
const i = this.items.indexOf(item)
if (i > -1) {
this.items.splice(i, 1)
}
}
}
}
</script>
<style>
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.slide-fade-enter-active {
transition: all 0.3s ease-out;
}
.slide-fade-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter-from,
.slide-fade-leave-to {
transform: translateX(20px);
opacity: 0;
}
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
</style>
官网文档: https://cn.vuejs.org/guide/built-ins/transition.html

浙公网安备 33010602011771号