vue 展开收起的过渡效果
做的一个项目当中需要做一个组件,传入数组,用v-for
生成表单,可以展开和收起,展开收起时需要有过渡的效果
在vue里面提供了<transtion></transtion>
和<transition-group></transition-group>
两个组件,<transtion>
用于普通组件元素,不能用于v-for
,<transition-group>
可用于v-for
的场景,是对遍历出来的项做过渡,而我的展开收起需要对整个容器进行过渡,因此需要手动添加过渡效果
这里是对高度变化进行过渡,因此需要满足让高度发生变化这个条件,即对容器设置高度,由于表单是遍历出来的,表单项的布局使用的是栅格
由于容器高度不确定,并且收起按钮位置固定右下角,当剩余位置宽度不够时,另占一行,容器高度需要动态计算,收起时的高度也需要动态计算
思路:给容器设置高度,高度为计算所得,收起时添加一个css类去改变容器高度
<div class="searform-box">
<el-form>
<div :style="{'height': transtionHeight + 'px'}" :class="['transtion', {'expand': !isExpand }]">
<el-row :gutter="24">
<el-col
v-for="(item, index) in arrays"
:class="['search-form-item', {'show': !isExpand && index >= EXPAND_SHOW_COUNT }]"
:span="span">内容</el-col>
</el-row>
</div>
</el-form>
</div>
因为收起时的高度是用css去控制的,并且是可变的,因此在css里面用--
声明一个变量expandHeight
,在.expand{}
当中使用var()
使用变量
.searform-box{
--expandHeight: 50px;
.show{
opacity: 0;
}
.expand{
height: var(--expandHeight) !important;
}
.transtion{
transition: all 0.3s ease;
overflow: hidden;
position: relative;
.search-form-item{
height: 50px;
transition: all 0.3s ease;
}
}
}
使用js计算高度
// 行高
public readonly ROW_HEIGHT = 50
// 操作按钮宽度
public readonly OPTION_WIDTH = 220
// 栅格
public readonly ROW_SPAN = 24
// 收起时显示个数
public readonly EXPAND_SHOW_COUNT = 3
// 计算容器高度
public setSearchBoxStyle() {
let height = 0
// 容器节点
const transitionBox = document.getElementsByClassName('transtion')[0] as HTMLElement
// 循环的项
const formItems = document.getElementsByClassName('search-form-item')
if (formItems && formItems.length > 0 && this.isExpand) {
// 展开
// 循环出来的所有项所占高度
height = this.ROW_HEIGHT * Math.ceil((this.span * this.queryItems.length) / this.ROW_SPAN)
// 最后一项
const lastFormItem = formItems[formItems.length - 1] as HTMLElement
// 最后一项右侧到容器右侧的宽度,即所剩宽度
const width = transitionBox.clientWidth - lastFormItem.offsetLeft - lastFormItem.clientWidth
// 如果剩余宽度不够,放不下按钮,就再加一行的高度
if (width < this.OPTION_WIDTH) {
height += this.ROW_HEIGHT
}
} else if (this.queryItems && !this.isExpand) {
// 收起
// 收起默认就一行
height = this.ROW_HEIGHT
// 收起时最后一项
const lastIndex = formItems.length > this.EXPAND_SHOW_COUNT ? this.EXPAND_SHOW_COUNT - 1 : formItems.length - 1
const lastFormItem = formItems[lastIndex] as HTMLElement
const width = transitionBox.clientWidth - lastFormItem.offsetLeft - lastFormItem.clientWidth
if (width < this.OPTION_WIDTH) {
height = this.ROW_HEIGHT * 2
}
// 设置css当中expandHeight变量的值
const searchFormBox = document.getElementsByClassName('searform-box')[0] as HTMLElement
searchFormBox.style.setProperty('--expandHeight', height + 'px')
}
return height
}
/*
* 表单项栅格计算,根据屏幕宽度动态计算项的所占份额
*/
public setSpan(val: number) {
if (val > 1440) {
this.span = 6;
}
if (val < 1450 && val > 750) {
this.span = 8;
}
if (val > 550 && val < 750) {
this.span = 12;
}
if (val < 550) {
this.span = 24;
}
this.transtionHeight = this.setSearchBoxStyle()
}
由于是公司项目,完整代码不方便贴,请见谅