Vue中的CSS动画原理
当使用transition 标签包裹标签时,Vue会自动分析其css样式,从而构建动画流程。
下图中的点的开头到结尾即为一个动画流程,当一个动画流程执行时,内部被transition 标签包裹的标签瞬间增加两个fade-enter 和 fade-enter-active标签,在动画的第一帧执行结束后,fade-enter去除,同时加上fade-enter-to,在动画执行借宿的瞬间会把fade-enter-active 和 fade-enter-to 两个 class都去除
动画从显示到隐藏的原理与上述流程相似
<style>
.fade-enter {
opacity: 0;
}
.fade-enter-active {
transition: opacity 2s;
}
.fade-leave-to {
opacity: 0;
}
.fade-leave-active {
transition: opacity 2s;
}
</style>
<div id="app">
<transition name="fade">
<div v-if="show">
hello box
</div>
</transition>
<button @click="hdclick">切换</button>
</div>
<script>
var app = new Vue({
el:"#app",
data: {
show: true
},
methods: {
hdclic: function(){
this.show = ! this.show
}
}
})
</script>
由于在transition 上设置的 name 为 fade,所以在style中的样式以fade开头,如果在trasition中不设置属性名,style中的样式即为v开头,例如v-enter
使用Animate.css 库
在Animate官网下载后引入改css文件
<link rel="stylesheet" type="text/css" href="animate.css">
使用了该css库,我们就不用自己写style了
<div id="app">
<transition enter-active-class="animated swing"
leave-active-class="animated shake">
<div v-if="show">
hello world
</div>
</transition>
<button @click="hdclick">切换</button>
</div>
在transition 标签中定义 animate 库中的样式enter-active-class 与 leave-active-class。在使用Animate.css 库时,要使用自定义css名,在css中必须包含animated ,然后在后面添加效果,如上代码,leave-active-class="animated shake"表示使用animated中的shake效果
apper
如果要在页面刷新的时候也加上动画效果,则需要加上appear 和 appear-active-class
<transition name="fade"
appear
enter-active-class="animated swing"
leave-active-class="animated shake"
appear-active-class="animated swing"
>
同时使用过渡和动画
若想在 Animate.css 库所提供的动画效果上再加入过渡的动画效果,可在在 animated 的 class 之后再添加 过渡动画的 CSS class
<style>
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 3s;
}
</style>
<transition
type="transition"
name="fade"
appear
enter-active-class="animated swing fade-enter-active"
leave-active-class="animated shake fade-leave-active"
appear-active-class="animated swing"
>
在animate中动画执行时1s,在过渡的动画中我们所设置的为3秒,这个时候我们在transition 里面添加属性 type,Vue就会使用type中所定义的类型动画执行时长。如果想自定义执行的时长,可以通过 :duration 属性来进行设置,:duration=“5000”,时长为5s,:duration="{ enter: 5000, leave: 10000 }",单独设置入场和出场的动画时长
Vue中的JS动画
使用Vue中的动画钩子
<div id="app">
<transition name="fade"
@before-enter="handleBeforeEnter"
@enter="handleEnter"
@after-enter="handleAfterEnter">
<div v-if="show">
hello world
</div>
</transition>
<button @click="hdclick">切换</button>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
show: true
},
methods: {
hdclick: function(){
this.show = ! this.show
},
handleBeforeEnter: function(el){
el.style.color = 'red'
},
handleEnter: function(el, done){
setTimeout(() => {
el.style.color = 'green'
},2000)
setTimeout(() => {
done()
},4000)
},
handleAfterEnter: function(el){
el.style.color = "#000"
}
}
})
</script>
在transition 中我们绑定了三个事件
@before-enter=“handleBeforeEnter”
@enter=“handleEnter”
@after-enter=“handleAfterEnter”
before-enter会接收到一个参数el,表示transition中所包裹的标签
enter会接受到两个参数,el和done,分别表示transition中所包裹的标签和回调函数,在setTimeout 执行完后调用触发after-enter
出场动画的钩子为before-leave 、leave 和 after-leave,用法与入场动画的差不多
velocity.js
在 velocity.js 官网 下载 velocity.js 文件,并引入
<script src="velocity.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
show: true
},
methods: {
hdclick: function(){
this.show = ! this.show
},
handleBeforeEnter: function(el){
el.style.opacity = 0
},
handleEnter: function(el, done){
Velocity(el,{opacity: 1}, {duration: 1000, complete: done})
},
handleAfterEnter: function(el){
alert('动画结束')
}
}
})
</script>
在BeforeEnter我们把透明图设为0,在enter的时候Enter我们传入参数el,{opacity: 1}, {duration: 1000, complete: done},这里注意Velocity v要大写
多元素的过渡动画
<style>
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 1s;
}
</style>
<div id="app">
<transition mode="out-in" name="fade">
<div v-if="show" key="hello">hello world</div>
<div v-else key="bye">Bye World</div>
</transition>
<button @click="hdleClick">切换</button>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
show: true
},
methods: {
hdleClick: function(){
this.show = ! this.show
}
}
})
</script>
通过设置key值,让Vue不复用dom
通过给transition 添加 mode 属性,out-in 、in-out来达到切换时的出场入场顺序效果
多个组件间过渡动画
<div id="app">
<transition mode="out-in" name="fade">
<child v-if="show"></child>
<child-one v-else></child-one>
</transition>
<button @click="hdleClick">切换</button>
</div>
<script>
Vue.component('child',{
template: '<div>child</div>'
})
Vue.component('child-one',{
template: '<div>child-one</div>'
})
var vm = new Vue({
el: "#app",
data: {
show: true
},
methods: {
hdleClick: function(){
this.show = ! this.show
}
}
})
</script>
</body>
Vue中的列表过渡
<style>
.v-enter, .v-leave-to{
opacity: 0;
}
.v-enter-active, .v-leave-active {
transition: opacity 1s;
}
</style>
<div id="app">
<transition-group>
<div v-for="item of list" :key="item.id">{{item.title}}</div>
</transition-group>
<button @click="hdleClick">Add</button>
</div>
<script>
var count = 0;
var vm = new Vue({
el: "#app",
data: {
list:[]
},
methods: {
hdleClick: function(){
this.list.push({
id: count++,
title: 'hello box'
})
}
}
})
</script>
通过transition-group来实现列表的动画过渡效果
列表在循环过后会生成多个div标签,我们通过transition-group包裹这些div标签相当于如下代码
<transition>
<div>hello box</div>
</transition>
<transition>
<div>hello box</div>
</transition>
动画封装
通过在组件中封装模板样式,结合动画钩子实现动画的封装,在使用的时候只需添加相应的show属性即可
<div id="app">
<fade :show="show">
<div>hello box</div>
</fade>
<fade :show="show">
<h1>hello box</h1>
</fade>
<button @click="hdclick">toggle</button>
</div>
<script>
Vue.component('fade',{
props: ['show'],
template: `
<transition @before-enter="handleBeforeEnter"
@enter="handleEnter"
@after-enter="handleAfterEnter">
<slot v-if="show"></slot>
</transition>
`,
methods: {
handleBeforeEnter: function(el){
el.style.color = 'red'
},
handleEnter: function(el,done){
setTimeout(() => {
el.style.color = 'green'
},2000)
setTimeout(() => {
done()
},4000)
},
handleAfterEnter: function(el){
el.style.color = "#000"
}
}
})
var vm = new Vue({
el: "#app",
data: {
show: true
},
methods: {
hdclick: function(){
this.show = ! this.show
}
}
})
</script>
</body>