序言
相信我们偶尔会遇到一种需求,按下某个按钮,触发事件,事件回调里让某个元素执行CSS定义好的Animation动画。
首先这个动画是绑定在元素的Class属性来对动画进行定义,会在第一次加载时执行。但我们的需求明显不需要他上来就执行。我们需要动态执行并且能重复执行。
那么如何实现呢,在网上查找到的方法基本都是拿到元素后,使用JQuery的removeClass来控制样式的清除。但是Vue不建议进行dom元素的操作,甚至uniapp里没有Window,自然没有document函数库更还拿不到到元素(特别view),那我们怎么退而求其次呢。
不浪费大家时间 先给出总结:
v-bind元素上绑定class**--->nextTick中执行清除data中的class--->**异步执行赋值data中的class
详细分析
首先给出前置的代码 这里用的uniapp展示,因为他限制最大最麻烦,其他vue的可以照葫芦画瓢更方便。
<!-- HTML部分 -->
<view :class="className">切入动画实践</view>
<button @click="changeClass()">点击动画</button>
动画是网上找的,太长就省略了
@-webkit-keyframes shake {
...
}
@keyframes shake {
...
}
.shake {
-webkit-animation-name: shake;
animation-name: shake;
}
.animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
接下来是JS
data() {
return {
classname:''
}
},
methods:{
changeClass(){
this.classname=''//清空样式
this.classname='animated shake'//设置动画
}
}
首先是绑定用的classname自然不用说,动态绑定能让我们后续可以绑上想要实现的动画,关键在于如果我们直接使用按钮绑定的回调,直接更改classname,那么我们会发现什么变化都没有。
因为我们修改了classname,导致回流,这也是实现动画执行的一环。但问题是,目前的修改是不会显示在页面上的,此时操作DOM,只会更改在虚拟dom中,而vue还没更新页面。
那我们都应该知道此时应该使用**nextTick()**来延迟执行对dom的操作。此处本人表述不清,不太懂nextTick应用场景的朋友请自行官网观看深入响应式原理 — Vue.js
data() {
return {
classname:''
}
},
methods:{
changeClass(){
this.$nextTick(function(){
this.classname=''//清空样式
this.classname='animated shake'//设置动画
})
}
}
设置完后,我们点击按钮,理应看到动画执行了,实际上动画的确执行了。但是当我们再次点击时就会发现,动画并没有执行,这是为什么呢?
原因就在于 Class="animated shake" 切换为Class="" 再切换成Class="animated shake"连续一起了,而回流和动画执行都是JS执行完后,才判定是否改变,需不需要回流,异步执行的,所以根本没有监测到Class改变了。所以非常简单 ,我们再给Class="animated shake"嵌套一个异步即可。
data() {
return {
classname:''
}
},
methods:{
changeClass(){
let that=this//如果定时器用普通函数就需要that哦,不然拿不到this
this.$nextTick(function(){
this.classname=''//清空样式
setTimeout(()=>{
that.classname='animated shake'//设置动画
},0)
})
}
}
当然你也可以不使用nextTick,使用两个定时器一样可以实现。原理就是两个异步,第一次延迟设置样式看到回流后的效果,第二次隔开清除样式再次设置动画。
现在我们可以很舒服的通过JS动态绑定我们要的动画样式,并且重复执行。类似的Dom操作也可以从此得到启发,至于测试其他情况就请大家去尝试尝试啦!~
版权归原作者 Genting丶incubus 所有, 如有侵权,请联系我们删除。