css实现折叠面板动画本是一件容易的事情,但是,若使用height控制,需要height已知,(当然,使用max-height控制,然后给一个足够大的max-height也是可以的);若使用scale,父容器的高度又未能随动画一起变化,本文讲述如何在vue中使用js动画实现折叠面板动画功能。
1. 理论基础
2. 样式
// collapse-transition.css
.collapse-transition {
transition: height .3s ease;
overflow: hidden;
}
3. 动画函数
// TransitionFunction.js
function Transition () {
if (new.target !== Transition) {
throw new TypeError('Cannot call a class as a function')
}
}
Transition.CLASS_NAME = 'collapse-transition'
Transition.prototype.beforeEnter = function (el) {
el.classList.add(Transition.CLASS_NAME)
el.style.height = 0
}
Transition.prototype.enter = function (el) {
if (el.scrollHeight !== 0) {
el.style.height = el.scrollHeight + 'px'
} else {
el.style.height = 0
}
}
Transition.prototype.afterEnter = function (el) {
el.classList.remove(Transition.CLASS_NAME)
el.style.height = ''
}
Transition.prototype.beforeLeave = function (el) {
el.classList.add(Transition.CLASS_NAME)
el.style.height = el.scrollHeight + 'px'
}
Transition.prototype.leave = function (el) {
if (el.scrollHeight !== 0) {
el.style.height = 0
}
}
Transition.prototype.afterLeave = function (el) {
el.classList.remove(Transition.CLASS_NAME)
el.style.height = ''
}
export default Transition
4. 折叠组件
// CoreCollapseTransition.js
import './collapse-transition.css'
import Transition from './TransitionFunction'
export default {
name: 'CoreCollapseTransition',
functional: true,
render: function (createElement, context) {
const data = {
on: new Transition()
}
return createElement('transition', data, context.children)
}
}
5. 面板组件
// CoreCollapse.vue
<template>
<div>
<div @click="collapse = !collapse">
{{ collapse ? '折叠' : '展开' }}
</div>
<core-collapse-transition>
<div v-show="collapse">
<slot></slot>
</div>
</core-collapse-transition>
</div>
</template>
<script>
import CoreCollapseTransition from './CoreCollapseTransition'
export default {
components: {
CoreCollapseTransition
},
data () {
return {
collapse: true
}
}
}
</script>
6. 使用示例
// Demo.vue
<template>
<div>
<core-collapse>
<h1>Hello world</h1>
</core-collapse>
<core-collapse>
<h1>Hello world</h1>
</core-collapse>
<core-collapse>
<h1>Hello world</h1>
</core-collapse>
</div>
</template>
<script>
import CoreCollapse from '../components/CoreCollapse'
export default {
components: {
CoreCollapse
}
}
</script>
7. 踩坑记录
本人曾尝试使用es6的class语法来实现步聚3中的TransitionFunction,一直未能实现动画功能,尚未发现具体问题在哪里,代码如下,欢迎留言指正。
// 有问题的版本,尚不清楚问题在哪里
class Transition {
static CLASS_NAME = 'collapse-transition'
beforeEnter (el) {
el.classList.add(Transition.CLASS_NAME)
el.style.height = 0
}
enter (el) {
if (el.scrollHeight !== 0) {
el.style.height = el.scrollHeight + 'px'
} else {
el.style.height = 0
}
}
afterEnter (el) {
el.classList.remove(Transition.CLASS_NAME)
el.style.height = ''
}
beforeLeave (el) {
el.classList.add(Transition.CLASS_NAME)
el.style.height = el.scrollHeight + 'px'
}
leave (el) {
if (el.scrollHeight !== 0) {
el.style.height = 0
}
}
afterLeave (el) {
el.classList.remove(Transition.CLASS_NAME)
el.style.height = ''
}
}
export default Transition