transition是vue提供用来实现过渡动画的,可以轻松实现排序,删除,新增等各种动画。但是最近使用transition来实现展开,收起动画时,发现最简便的设置height属性的transition过渡是不起作用的。这种情况是基于我们不知道容器div的高度的情况下。如果div的高度是既定的,那么通过transition实现展开收起动画是能轻松搞定的。
对于不定高的div的展开收起动画,我们就需要借助transition的回调函数来来实现了。
不啰嗦,直接看代码
<template> <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" > <slot></slot> </transition> </template> <script> export default{ data(){ return { } }, methods:{ beforeEnter(el){ el.className=el.className+' my-transition'; el.style.height = '0'; }, enter(el){ el.style.height = el.scrollHeight + 'px'; }, afterEnter(el){ el.className=el.className.replace("my-transition",''); el.style.height = ''; }, enterCancelled(el){ }, beforeLeave(el){ el.style.height = el.scrollHeight + 'px'; }, leave(el){ let ht=el.scrollHeight; el.className=el.className+' my-transition'; el.style.height = 0; }, afterLeave(el){ el.className=el.className.replace("my-transition",''); el.style.height = ''; }, leaveCancelled(el){ } } } </script> <style> .my-transition{transition: .3s height ease-in-out/* , 10.5s padding-top ease-in-out, 10.5s padding-bottom ease-in-out */} </style>
这里面transition的回调函数会以此根据过渡的不同状态调用,详细的vue官网有介绍,这里就不赘述了。
展开收起实现的关键就是beforeEnter回调中设置高度为0,并且添加上有transition效果的样式。在enter回调中获取div的高度,并且设置div高度。这样就实现了从0到height高度的展现过渡动画,收起的动画与此相反。
而这其中有一个知识点,就是el.scrollHeight,这个属性用来获取div中内容的实际高度,不管div是否处于display:none状态,都能获取到。这为我们获取div的内容高度提供了遍历。
当然,上面只是最简单实现展开收起的过渡动画,还有许多细节需要我们考虑:
比如:1,进行展开收起动画的div需要overflow:hidden样式,如果作为通用组件,那么我们不能要求使用者的动画元素具有此属性,就需要我们自己给el元素添加此样式,并保留原来的overflow属性,在动画结束后恢复原样。
2,进行展开收起动画的div可能具有padding属性,这时候我们还需要对padding属性进行动画过渡。比如div有padding-top:50px;那么这个展开动画必须要处理padding-top的从0到50的动画过程,这样过渡动画才能流畅。
最后,如果你比较懒,也可是使用element提供的展开收起动画的组件进行实现。但,我们终究需要提高的,多学一些知识点和技巧对自己是有好处的,谁知道以后elementUI会不会被淘汰呢,就如同jquery一样。如果你现在只是精通jquery,而没有跟上前端的脚步,掌握前端自动化的东西是很难找到一份顺心的功能。
毕竟,我们没能力改变环境,但我们有能力适应环境。