Vue动画
一 使用过渡类名实现过渡
官方文档中说明,Vue
提供了 transition
的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡
- 条件渲染 (使用
v-if
) - 条件展示 (使用
v-show
) - 动态组件
- 组件根节点
一个例子:
<style>
.slide-fade-enter,
.slide-fade-leave-to {
opacity: 0;
}
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
</style>
<div id="app">
<input type="button" value="toggle" @click="toggle">
<transition name="slide-fade">
<h3 id="h3" v-show="flag">{{msg}}</h3>
</transition>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
msg: "hello",
flag: true
},
methods: {
toggle() {
this.flag = !this.flag;
}
}
})
</script>
对于想要使用过渡/动画的Dom
元素,使其被包裹于transition
标签即可。
在进入/离开过渡时,会有6个class
切换:
v-enter
:进入过渡的开始状态,在元素被插入之前生效,在元素被插入之后的下一帧移除。v-enter-active
:定义进入过渡生效的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。v-enter-to
:在元素被插入之后下一帧失效,v-enter
被移除,v-enter-to
在过渡/动画完成之后移除。v-leave
:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。v-leave-active
:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。v-leave-to
: 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时v-leave
被删除),在过渡/动画完成之后移除。
对于这6个class
,如果我们不指定transition
的name
属性,则v-
是默认前缀,如果自定义了name
属性,那么v-enter
会被替换为transitionname-enter
。
实现动画时,只需要为这六个class
添加样式即可。
二 使用第三方库animate.css实现动画
aninate.css
库中包含了许多的常用动画,我们可以使用。
Vue中提供了以下类名,这些类名优先级高于普通类名,使得我们可以优良的结合Vue 的过渡系统和其他第三方 CSS 动画库如animate.css
:
enter-class
enter-active-class
enter-to-class
(2.1.8+)leave-class
leave-active-class
leave-to-class
(2.1.8+)
一个使用第三方库animate.css
的例子:
<transition
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight">
<p v-show="flag">{{msg}}</p>
</transition>
同时,transition
标签还具有:duration
属性,可以让我们自定义持续时间,如:
<transition :duration="1000">...</transition>
<transition :duration="{ enter: 500, leave: 800 }">...</transition>
三 使用钩子函数实现动画
可以在属性中声明 JavaScript 钩子:
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
<!-- ... -->
</transition>
首先,我认为有必要说明方法的执行顺序,当一个Dom
从无到有,顺序为beforeEnter->enter->afterEnter->beforeLeave->leave->afterLeave
,而当一个Dom
从有到无,顺序为beforeLeave->leave->afterLeave
。
下面是一个例子:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>钩子函数实现动画</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
/*画个小球*/
#ball {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: black;
}
</style>
</head>
<body>
<div id="app">
<input type="button" value="动画开始" @click="flag=!flag">
<br><br>
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled" @before-leave="beforeLeave" v-on:leave="leave"
v-on:after-leave="afterLeave">
<div id="ball" v-show="flag">
</div>
</transition>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: true,
msg: "hello"
},
methods: {
beforeEnter(el) {
// 设置小球开始动画之前的起始位置
console.log("进入beforeEnter...")
el.style.opacity = 0;
el.style.transform = "translate(0,0)";
},
enter(el, done) {
console.log("进入enter...")
// 不加不行
el.offsetWidth
// enter表示动画开始之后的样式,可以设置动画后的结束状态
el.style.opacity = 1;
el.style.transform = "translate(150px,450px)";
el.style.transition = "all 1s ease"
// 进入afterEnter方法
done();
},
afterEnter(el, done) {
console.log("进入afterEnter...")
this.flag = !this.flag;
},
enterCancelled(el) {
console.log("enterCancelled...")
},
beforeLeave(el) {
console.log("beforeLeave...")
},
leave(el) {
console.log("leave...");
},
afterLeave(el) {
console.log("afterLeave...")
}
}
})
</script>
</body>
</html>
这个例子展示了一个小球的动画以及执行顺序,大家可以把flag
的初始值分别设为true
和false
试试。
四 列表动画
列表动画需要使用transition-group
属性,且需对每一项添加:key
属性。
下面通过一个列表进行实例演示:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>列表动画</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
li {
border: 1px dashed #999;
line-height: 40px;
width: 100%;
}
li:hover {
background-color: pink;
transition: all 0.8s ease;
}
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateY(60px);
}
.v-enter-active,
.v-leave-active {
transition: all 0.6s ease;
}
/*v-move指的是元素移动时自动添加的类名*/
.v-move {
transition: all 0.6s ease;
}
.v-leave-active {
position: absolute;
}
</style>
</head>
<body>
<div id="app">
<div class="operation">
id: <input type="text" v-model="id">
name: <input type="text" v-model="name">
<input type="button" value="添加" @click="add">
</div>
<transition-group appear tag="ul">
<li v-for="(per,i) in list" :key="per.id" @click="del(i)">{{per.id}}--{{per.name}}</li>
</transition-group>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
id: "",
name: "",
list: [
{
id: 1, name: "严嵩"
},
{
id: 2, name: "秦桧"
},
{
id: 3, name: "魏忠贤"
}
]
},
methods: {
add() {
this.list.push({
id: this.id,
name: this.name
});
this.id = "";
this.name = "";
},
del(i) {
this.list.splice(i, 1)
}
}
})
</script>
</body>
</html>
在该实例中实现了列表元素添加动画,删除动画。
除此以外,给transition-group
添加appear
属性可以添加开始入场动画,查看源代码,发现transition-group
默认被渲染为span
,事实上,我们还可以指定tag
属性,实现将其渲染成不同的元素。