vue(uni-app)中v-if与动画效果冲突的解决办法

时间:2024-12-17 07:03:43

这两天终于真正接触到了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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

index.vue

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

js:

methods:{
	create(){
		this.active=true
		this.$nextTick(()=>{
			setTimeout(()=>{
				this.textShow=true
			},50)
		})
	},
	//...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

$nextTick() 的用法:

Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的 MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0)代替。

所以,关于这个api的使用,有一下几点“规定”:

  • 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在()的回调函数中

created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进()的回调函数中。与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。

  • 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进()的回调函数中。

实现一个简单的 $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]();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
'
运行

如何开启一个uni-app项目:

  • 在HBuilderX中,直接点击“创建项目”->“uni-app项目”即可
  • 在其他编译器如VSCode中,可以借助【cli工具】(命令行):vue create -p dcloudio/uni-preset-vue 项目名称,回车 选择“默认模板”即可