这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
前言
今天来搞搞过渡动画,搞完这个过渡下一篇咋们就做个Todo案例,因为有用到这个知识点。然后这篇文章我们主要就讲解其中的一两个部分啊,包括单元素/组件的过渡、列表的进入/离开过渡、JavaScript 动画钩子;因为其实内容挺多的,更多内容还需要看官方文档的介绍。
单元素/组件的过渡
概念: Vue 在元素显示隐藏时, 提供了 transition 的封装组件,可以给任何元素和组件添加进入/离开过渡
语法:
<transition name="过渡css名">单一标签</transition>
栗子: 控制元素的显示与隐藏
<div id="app">
<!--
被transition标签包裹的元素在其显示隐藏时,六个不同的阶段会自动添加6个class名
元素进入的第一帧 [transition name 属性]-enter
元素进入中 [transition name 属性]-enter-active
元素进入的最后一帧 [transition name 属性]-enter-to
元素离开的第一帧 [transition name 属性]-leave
元素离开中 [transition name 属性]-leave-active
元素离开的最后一帧 [transition name 属性]-leave-to
-->
<transition name="fade">
<div class="box" v-if="show"></div>
</transition>
<button @click="show = !show">show/hidden</button>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
show: true
}
})
</script>
<style>
.box {
width: 100px;
height: 100px;
background-color: green;
}
.fade-enter, .fade-leave-to{
/*元素进入动画第一帧 类名*/
opacity: 0;
transform: translateX(300px);
width: 0;
height: 0;
}
.fade-enter-active, .fade-leave-active {
/*元素进入整个过程中 类名*/
transition: all .5s linear;
}
.fade-enter-to, .fade-leave {
/*元素进入动画最后一帧 类名*/
opacity: 1;
transform: translateX(0);
width: 100px;
height: 100px;
}
</style>
然后大概的效果就是这样,有了动画看起来就没有这么生硬的感觉。
注意:
transition 标签内只能包含一个直接子元素
transition 标签的name属性可以省略, 省略后元素进入离开时类名默认使用v-开头,例: v-enter,v-enter-to,v-leave,v-leave-to。
列表的进入/离开过渡
概念: 因为transition标签内部只能监听单个节点,或同一时间渲染多个节点中的一个。所以transition标签内部无法监听多个节点的。所以vue提供了 <transition-group>
组件事件内部监听多个节点的进入离开
语法:
<transition-group name="过渡css名">多个标签</transition-group>
<div id="app">
<transition-group name="fade">
<p v-for="c in arr" :key="c">{{c}}</p>
</transion-group>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
arr: ['a', 'b', 'c', 'd', 'e']
}
})
</script>
<style>
.fade-enter,
.fade-leave-to {
transform: translateX(100px);
}
.fade-enter-active,
.fade-leave-active {
transition: all .5s linear;
}
.fade-enter-to,
.fade-leave {
transform: translateX(0);
}
</style>
注意:
1、在transition-group组件中,列表渲染的key不能使用index。index作为key在添加或者删除时会导致不是正确> 的DOM节点被移除
2、transition-group会被vue默认渲染成一个span元素,如果你想设置transition-group组件渲染输出的节点可以设> 置其tag属性,例 tag="ul",transition-group组件就会被渲染成ul标签,参考如下代码和图示
// 主要看哦,我这里是设置了tag属性的为 ul的
<transition-group tag="ul" name="move">
<li v-for="todo in todos" :key="todo.id">
{{todo.text}}
</li>
</transition-group>
接下来上图对比一哈
JavaScript 动画钩子
概念: 无论transition 和 transition-group 标签都支持使用动画js钩子。动画的钩子就是元素在整个动画过渡中默写特殊的时间点。当动画到达这些时间点时就会触发js钩子所绑定方法。有了js动画钩子就可以实现一些复杂的动画。
语法: 动画钩子就是vue提供的一些自定义事件,监听响应的事件触发绑定的函数
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
<!-- ... -->
</transition>
<transition-group
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
<!-- ... -->
</transition-group>
注意: 动画钩子事件会将当前动画元素作为参数传入到函数内部
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<div v-show="show" class="box"></div>
</transition>
<button @click="show = !show">show/hidden</button>
</div>
<script>
console.log(Velocity)
new Vue({
el: "#app",
data: {
show: true
},
methods: {
beforeEnter(el) {
console.log(el, '元素将要显示')
el.style.opacity = 0
},
enter(el, done) {
console.log('元素正在显示')
Velocity(el, {
opacity: "1",
translateY: '30px',
}, {
duration: 400,
easing: "swing",
loop: 2,
complete: done // 动画结束后触发done表示自定义动画结束
});
},
afterEnter(el) {
el.style.opacity = 1
// console.log(el.offsetHeight)
console.log('元素显示完毕')
}
}
})
</script>
动画钩子事件会中enter事件与leave事件除了会默认传递第一个参数el(当前动画元素)以外,还会传递第二个参数 done,done 是一个方法用来告诉Vue当前元素的自定义动画已经结束,动画钩子才会执行下一步 after-enter 或者after-leave。如果自定义动画效果结束后不调用done可能会导致动画元素样式不更新。
结尾
今天就先到这里啦!我们下期再见!码字不易,觉得不错的可以动动小指头点点赞啥的哟~