vue.js中的過渡動畫效果(transition+animate.css+velocity.js)

對於“數據優先”的Vue來說,沒有了dom的操作,過渡效果該如何實現?

其實,vue也不是完全失去了對dom的操作,仍然可以通過比如$refs獲取對應的dom元素


先看一個小demo:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
	</head>
	<body>
		<div id="root">
			<div v-show="show">Hello world</div> 
			<button @click="handleClick">toggle</button>
		</div>
		<script>
			var vm=new Vue({
				el:'#root',
				data:{
					show:true
				},
				methods:{
					handleClick:function(){
						this.show=!this.show
					}
				}
			})
		</script>
	</body>
</html>

其效果如下:
在這裏插入圖片描述

但可以看到,其中文字“Hello world”的“行爲”非常生硬。一個元素尚且如此,更別說兩個元素來回切換的場景了。

爲此,vue提供了一個“進出過渡”的特效CSS語法。其使用前要先用<transition></transition> 包裹涉及到的所有標籤:
我們來看兩個元素的效果——修改上面demo-Hello world部分

<transition>
	<div v-if="show">Hello world</div>
	<div v-else>Bye world</div>
</transition>

保存一下,到頁面上看,會發現依然很“不爽”。這可能是因爲還沒有寫style的緣故:

.v-enter,.v-leave-to{   /* 過渡前 */
	opacity:0;
}
.v-enter-active,.v-leave-active{   /* 過渡中 */
	transition:opacity 1s;
}

做完這些我們就會發現。。。效果依然沒有出現!
這是爲什呢? ——Vue默認會【複用dom】,通俗地說,就是【緩存DOM】。要想解除這個,需要給每個元素加一個key

<transition mode="out-in">
	<div v-if="show" key="key1">Hello world</div>
	<div v-else key="key2">Bye world</div>
</transition>

這樣就可以了:
在這裏插入圖片描述

上面是多個元素的切換,那麼多個組件呢?
筆者建議最好採用動態組件的方式:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
	</head>
	<body>
		<div id="root">
			<component :is="type"></component>
			<button @click="handleClick">toggle</button>
		</div>
		<script>
			Vue.component('child',{
				template:'<div>Hello world</div>'
			})
			Vue.component('childs',{
				template:'<div>Bye world</div>'
			})
			var vm = new Vue({
				el: '#root',
				data: {
					type:'child'
				},
				methods: {
					handleClick: function() {
						this.type=this.type==='child'?'childs':'child'
					}
				}
			})
		</script>
	</body>
</html>

其實,在真正項目裏,很多時候筆者採用的就是這種方法:比如在一個vue多頁面(組件)的項目裏,頁面之間切換時有一個向左/右滑動的效果:

<transition :name="transitionName">
	<router-view class="Router" />
</transition>

//js-data
data(){
	retrun{
		transitionName:'slide-right',
		//...
	}
}
//js-watch
watch:{
	$route(to,from){   //導航發生變化,$route也就是會改變
		if(to.meta.index > from.meta.index){
			this.transitionName='slide-right'
		}else{
			this.transitionName='slide-left'
		}
	}
}

//css
.Router{
	position:absolute;
	width:100%;
	transition:all .8s ease;
}
.slide-left-enter,.slide-right-leave-active{
	opacity:0;
	transform:translate(100%,0);
}
.slide-left-leave-active,.slide-right-enter{
	opacity:0;
	transform:translate(-100%,0);
}

這樣的話,其app.vue裏的路由routes中每一項都要加上一個屬性:

meta:{index:數字};

emmmmmm…vue中使用第三方庫函數又是另一番體驗了:
讓我們把目光重新聚焦到本文第一例demo上,看一下animate.css的“風情”:

npm install animate.css
<link rel="stylesheet" href="./animate.css">

<div id="root">
	<transition
			enter-active-class="animated swing"
			leave-active-class="animated shake"
	>
			<div v-show="show">Hello world</div> 
			<button @click="handleClick">toggle</button>
	</transition>
</div>
<script>
	var vm=new Vue({
		el:'#root',
		data:{
			show:true
		},
		methods:{
			handleClick:function(){
				this.show=!this.show
			}
		}
	})
</script>

如上,swing和shake就是animate.css內部封裝好的兩種負責“抖動”動畫的類名。 —— 沒錯,它的實現原理就是@keyframes


說完了css,不妨再來看看JS:他也可以製造動畫效果 —— Velocity.js插件:

npm install velocity.js
<transition
		@before-enter="ha1"
		@enter="ha2"
		@after-enter="ha3"
>
	<div v-show="show">Hello</div>
</transition>

//js-methods
methods:{
	//這些函數會接收一個參數:指向綁定的dom
	ha1:function(el){
		el.style.opacity=0
	},
	ha2:function(el){
		Velocity(el,{opacity:1},{duration:1000,complete:done})
	},
	ha3:function(el){
		alert("動畫結束!")
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章