在插入、更新、移除 DOM
元素时,在合适的时候给元素添加样式类名,配合 CSS
样式使用,实现动画效果。
通俗来讲,就是将要进行动画操作的 DOM
元素用 transition
标签包裹起来。在此html元素运动前,运动中,运动后这三个时候 vue
会给此 DOM
元素添加不同的 class
,然后配合 CSS
样式,实现动画效果。
示例:
<template>
<div>
<button @click="bol = !bol">隐藏/显示button>
<transition>
<h1 v-show="bol">组件动画效果h1>
transition>
div>
template>
<script>
export default {
name: "TestDemo",
data() {
return { bol: true };
},
};
script>
<style>
/* 进入:始状态 */
.v-enter {
transform: translateX(-100%);
color: red;
}
/* 进入:末状态 */
.v-enter-to {
transform: translateX(0);
color: yellow;
}
/* 进入动画 */
.v-enter-active {
transition: 10s;
color: linear-gradient(red,yellow);;
}
/* 离开:始状态 */
.v-leave {
transform: translateX(0);
}
/* 离开:末状态 */
.v-leave-to {
transform: translateX(-100%);
}
/* 离开动画 */
.v-leave-active {
transition: 1s;
}
style>
Vue
的内置动画标签: transition
transition
标签只能包含 1 个元素;如果里面写了多个元素,则只生效第一个transition
包裹的标签需要设置 v-show
/ v-if
属性控制元素的显示.v-enter
始状态、.v-enter-to
末状态、.v-enter-active
进入动画.v-leave
始状态、.v-leave-to
末状态、.v-leave-active
离开动画.v-enter
、 .v-leave
定义了动画的初始状态,在里面可以定义初始的位置,颜色,字体等。.v-enter-to
、 .v-leave-to
定义了动画的最终状态,这两个类的定义最好和 DOM 的 class保持一致,否则动画结束后会瞬间从 .v-enter-to
、 .v-leave-to
的样式转变为 DOM 的样式(实例一,实例二).v-enter-active
、 .v-leave-active
定义了动画的渐变规则,比如是位置渐变的话会定义渐变的时间,路径;颜色渐变的话会定义颜色相关的渐变规则会从红色渐变为黄色
<template>
<div>
<button @click="bol = !bol">隐藏/显示button>
<transition>
<h1 v-show="bol" class="demo">组件动画效果h1>
transition>
div>
template>
<script>
export default {
name: "TestDemo",
data() {
return { bol: true };
},
};
script>
<style>
.v-enter-active,
.v-leave-active {
transition: 10s !important;
color: linear-gradient(red,yellow) !important;
}
.demo {
color: yellow;
}
.v-enter,
.v-leave-to {
transform: translateX(-50%);
color: red;
}
style>
会从红色渐变为黄色,然后瞬间变为黑色
<template>
<div>
<button @click="bol = !bol">隐藏/显示button>
<transition>
<h1 v-show="bol" class="demo">组件动画效果h1>
transition>
div>
template>
<script>
export default {
name: "TestDemo",
data() {
return { bol: true };
},
};
script>
<style>
.v-enter,
.v-leave-to {
transform: translateX(-50%);
color: red;
}
.v-enter-to,
.v-leave {
transform: translateX(0);
color: yellow;
}
.v-enter-active,
.v-leave-active {
transition: 10s !important;
color: linear-gradient(red, yellow) !important;
}
style>
用于自动生成 CSS 动画类名
transition
标签元素没有设置 name
属性,则对应的动画类名为 v-XXX
name
属性,则对应的动画类名为 属性值-XXX
tansition
标签时,我们可以通过 name
属性给各个 transition
标签指定不同的 CSS
动画效果一开始就生效显示动画
in-out
: 新元素先进行过渡,完成之后当前元素过渡离开out-in
: 当前元素先进行过渡,完成之后新元素过渡进入<template>
<div>
<button @click="bol = !bol">隐藏/显示button>
<transition name="test" appear>
<h1 v-show="bol">组件动画效果h1>
transition>
div>
template>
<script>
export default {
name: "TestDemo",
data() {
return { bol: true };
},
};
script>
<style>
.test-enter,
.test-leave-to {
transform: translateX(-50%);
color: red;
}
.test-enter-to,
.test-leave {
transform: translateX(0);
color: yellow;
}
.test-enter-active,
.test-leave-active {
transition: 10s !important;
color: linear-gradient(red,yellow) !important;
}
style>
transition
标签只能包含 1 个元素、 transition-group
标签可以包含多个元素transition-group
标签里面的元素需要设置 key
属性,作为当前元素的唯一标识transition
标签一样<template>
<div id="app">
<button @click="isEditing = !isEditing">切换button>
<transition-group appear>
<h1 v-if="isEditing" key="save">Saveh1>
<h1 v-if="!isEditing" key="edit">Edith1>
transition-group>
div>
template>
<script>
export default {
name: "TestDemo",
data() {
return { isEditing: true };
},
};
script>
<style>
h1 {
transition: 3s;
position: absolute;
}
.v-leave {
opacity: 1;
}
.v-leave-to {
opacity: 0;
}
.v-enter {
opacity: 0;
}
.v-enter-to {
opacity: 1;
}
style>
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
methods: {
// --------
// 进入中
// --------
beforeEnter: function (el) {
console.log('beforeEnter');
console.log(el);
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
enter: function (el, done) {
console.log('enter');
console.log(el);
done()
},
afterEnter: function (el) {
console.log('afterEnter');
console.log(el);
},
enterCancelled: function (el) {
console.log('enterCancelled');
console.log(el);
},
// --------
// 离开时
// --------
beforeLeave: function (el) {
console.log('beforeLeave');
console.log(el);
},
leave: function (el, done) {
console.log('leave');
console.log(el);
done()
},
afterLeave: function (el) {
console.log('afterLeave');
console.log(el);
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
console.log('leaveCancelled');
console.log(el);
}
},
<template>
<div>
<button @click="bol = !bol">隐藏/显示button>
<transition name="fade">
<p v-if="bol">hellop>
transition>
div>
template>
<script>
export default {
name: "TestDemo",
data() {
return { bol: true };
},
};
script>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: all 3s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
width: 100px;
}
p {
border: 1px solid red;
width: 300px;
}
style>
<template>
<div>
<button @click="bol = !bol">隐藏/显示button>
<transition name="bounce">
<p v-show="bol" class="demo">组件动画效果p>
transition>
div>
template>
<script>
export default {
name: "TestDemo",
data() {
return { bol: true };
},
};
script>
<style>
.bounce-enter-active {
animation: bounce-in 5s;
}
.bounce-leave-active {
animation: bounce-in 5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
style>
npm install animate.css
import "animate.css"
transition
标签添加 name
属性 animate_animate、animate__bounce
enter-active-class
属性,指定进入动画:在样式库中挑一个进入的样式值,作为 enter-active-class
属性值leave-active-class
属性,指定退出动画:在样式库中挑一个退出的样式值,作为 leave-active-class
属性值<template>
<div>
<button @click="bol = !bol">隐藏/显示button>
<transition
name="animate__animated animate__bounce"
enter-active-class="animate__bounceIn"
leave-active-class="animate__bounceOut"
>
<p v-show="bol" name="animate_animate">组件动画效果p>
transition>
div>
template>
<script>
import "animate.css";
export default {
name: "TestDemo",
data() {
return { bol: true };
},
};
script>
JavaScript
过渡时,在 enter
和 leave
中必须使用 done
进行回调。否则,它们将被同步调用,过渡会立即完成。JavaScript
过渡的元素添加 v-bind:css="false"
,Vue
会跳过 CSS
的检测。这也可以避免过渡过程中 CSS
的影响。npm install velocity-animate
<template>
<div id="app">
<button @click="show = !show">显示/隐藏button>
<br />
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
v-bind:css="false"
>
<p v-show="show">hellop>
transition>
div>
template>
<script>
import Velocity from "velocity-animate";
export default {
name: "App",
data: function () {
return {
show: true,
};
},
methods: {
beforeEnter: function (el) {
el.style.opacity = 0;
},
enter: function (el, done) {
Velocity(
el,
{
rotateZ: "0deg",
translateY: "0px",
translateX: "0px",
opacity: 1,
},
{ complete: done }
);
},
leave: function (el, done) {
Velocity(
el,
{
rotateZ: "45deg",
translateY: "30px",
translateX: "30px",
opacity: 0,
},
{ complete: done }
);
},
},
};
script>
<template>
<div id="example-2">
<transition name="fade" mode="out-in">
<button v-if="isEditing" key="save" @click="isEditing = !isEditing">
Save
button>
<button v-else key="edit" @click="isEditing = !isEditing">Editbutton>
transition>
div>
template>
<script>
export default {
name: "TransitionTest",
data() {
return {
name: "TransitionTest",
isEditing: false,
};
}
};
script>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: all 1s;
}
.fade-enter {
opacity: 0;
transform: translateX(50px);
}
.fade-leave-to {
opacity: 0;
transform: translateX(-50px);
}
#example-2 {
position: relative;
padding: 100px;
}
#example-2 button {
position: absolute;
}
style>
<template>
<div id="transition-components-demo">
<button @click="view = 'VA'">abutton>
<button @click="view = 'VB'">bbutton>
<transition name="component-fade" mode="out-in">
<component v-bind:is="view">component>
transition>
div>
template>
<script>
import VA from "./VA.vue";
import VB from "./VB.vue";
export default {
name: "TransitionTest",
data() {
return {
view: "VA",
};
},
components: {
VA,
VB,
},
};
script>
<style scoped>
.component-fade-enter-active,
.component-fade-leave-active {
transition: opacity 2s ease;
}
.component-fade-enter,
.component-fade-leave-to {
opacity: 0;
}
style>
<template>
<div id="list-demo" class="demo">
<button v-on:click="add">Addbutton>
<button v-on:click="remove">Removebutton>
<transition-group name="list" tag="p">
<span v-for="item in items" :key="item" class="list-item">
{{ item }}
span>
transition-group>
div>
template>
<script>
export default {
name: "TransitionTest",
data() {
return {
items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
nextNum: 10,
};
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.items.length);
},
add: function () {
this.items.splice(this.randomIndex(), 0, this.nextNum++);
},
remove: function () {
this.items.splice(this.randomIndex(), 1);
},
},
};
script>
<style scoped>
.list-item {
display: inline-block;
margin-right: 10px;
}
.list-enter-active,
.list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to {
opacity: 0;
transform: translateY(30px);
}
style>