VUE动画Javascript钩子不生效问题记录
举例小球动画如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>小球动画</title> <style> /* 小球样式 */ .ball{ width: 15px; height: 15px; border-radius: 50%; background-color: red; } </style> </head> <body> <div id="app"> <input type="button" value="快到碗里来" @click="flag=!flag"> <transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter"> <div class="ball" v-show="flag"></div> </transition> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { flag: false, }, methods: { //开始动画之前 beforeEnter(el) { //起始位置 el.style.transform = 'translate(0,0)' }, enter(el) { //动画完成后的样式 el.style.transform = 'translate(150px,450px)' //动画过渡效果 el.style.transition = 'all 1s ease' }, afterEnter(el) { } } }) </script> </body> </html>
上面代码动画过渡效果是没有实现的,原因在于浏览器不会根据你js对style的修改实时更新,而一般是在当前js修改完毕之后,会对所有修改统一更新,而display:none(它本身是不能transition的)的状态切换影响了其他过渡效果的切换,毕竟为none的元素没法触发过渡。将offsetWidth打开,你会发现过渡生效了,原因在于取offsetWidth导致浏览器重绘,使后面的style修改前,display确确实实变为了block,从而消除了元素状态为none对过渡的这种影响。添加setTimeout,“打断”js的执行也可生效。
所以可以在enter函数中添加el.offsetWidth或el.offsetHeight
enter(el) { //也可使用offsetHeight el.offsetWidth el.style.transform = 'translate(150px,450px)' el.style.transition = 'all 1s ease' }
或者使用setTimeout
enter(el) { setTimeout(() => { //动画完成后的样式 el.style.transform = 'translate(150px,450px)' //动画transition样式 el.style.transition = 'all 1s ease' }, 20) },