vue(uni-app)中v-if與動畫效果衝突的解決辦法

這兩天終於真正接觸到了uni-app——其實就是一款基於vue的多端融合產品,它可以調用任意平臺的api,以達到“可以順利登陸各平臺”的目的。
寫demo的時候遇到點麻煩:
由於使用了v-if條件判斷,所以元素展示很“突兀”,定義的transform根本沒有效果!


解決辦法:

  1. 改用v-show
  2. 使用$nextTick() + setTimeout() 方法:

css:

.create-content{
	position:fixed;
	/* ... */
	transition:all .3s;
	opacity:0;
	transform:scale(0) translateY(200%);
}
.create__show{
	opacity:1;
	transform:scale(1) translateY(0);
}

index.vue:

<view v-if="active" class="create-content" :class="{'create__show':textShow}">
	
</view>

js:

methods:{
	create(){
		this.active=true
		this.$nextTick(()=>{
			setTimeout(()=>{
				this.textShow=true
			},50)
		})
	},
	//...
}

$nextTick() 的用法:

Vue 異步執行 DOM 更新。只要觀察到數據變化,Vue 將開啓一個隊列,並緩衝在同一事件循環中發生的所有數據改變。如果同一個 watcher 被多次觸發,只會被推入到隊列中一次。這種在緩衝時去除重複數據對於避免不必要的計算和 DOM 操作上非常重要。然後,在下一個的事件循環“tick”中,Vue 刷新隊列並執行實際 (已去重的) 工作。Vue 在內部嘗試對異步隊列使用原生的 Promise.thenMessageChannel,如果執行環境不支持,會採用 setTimeout(fn, 0)代替。

所以,關於這個api的使用,有一下幾點“規定”:

  • 在Vue生命週期的created()鉤子函數進行的DOM操作一定要放在Vue.nextTick()的回調函數中

created()鉤子函數執行的時候DOM 其實並未進行任何渲染,而此時進行DOM操作無異於徒勞,所以此處一定要將DOM操作的js代碼放進Vue.nextTick()的回調函數中。與之對應的就是mounted()鉤子函數,因爲該鉤子函數執行時所有的DOM掛載和渲染都已完成,此時在該鉤子函數中進行任何DOM操作都不會有問題 。

  • 在數據變化後要執行的某個操作,而這個操作需要使用隨數據改變而改變的DOM結構的時候,這個操作都應該放進Vue.nextTick()的回調函數中。

實現一個簡單的 $nextTick() 方法:

let callbacks=[];
let pending=false;
function nextTick(cb){
	callbacks.push(cb);
	if(!pending){
		pending=true;
		setTimeout(flushCallbacks,0);
	}
}
function flushCallback(){
	pending=false;
	const pipes=callbacks.slice(0);
	callbacks.length=0;
	for(let i=0;i<pipes.length;i++){
		pipes[i]();
	}
}

如何開啓一個uni-app項目:

  • 在HBuilderX中,直接點擊“創建項目”->“uni-app項目”即可
  • 在其他編譯器如VSCode中,可以藉助【cli工具】(命令行):vue create -p dcloudio/uni-preset-vue 項目名稱,回車 選擇“默認模板”即可
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章