如何实现手风琴组件高度自适应 + 高度动画

1 功能需求

1.1 打开合上面板的动画

// template
<div
	:style="{ height: height + 'rem' }"
>...</div>

// style
.animation {
	...
	transition: height 0.5s
}

// js
initHeight = 1
maxHeight = 2 // 经过复杂的js预计算获得,不好维护
height = initHeight
open = false

function changeHeight() {
	open = !open
	this.height = open ? maxHeight : initHeight
}

1.2 高度自适应,避免js计算

// template
<div
	:style="divStyle"
>...</div>

// style
.animation {
	...
	transition: height 0.5s
}

// js
initHeight = 1
open = false

get divStyle() {
	return open ? {} : { height: initHeight }
}

function changeHeight() {
	open = !open
}

2 功能冲突

自适应布局时height为auto,所以能自动根据content撑开,但是于此同时,也就破坏了height动画,因为height的from和to必须为某一定值而不是auto

3 解决方案

3.1 方案1 使用maxHeight(bad)

// js
maxHeight = 999
open = false

get divStyle() {
	return open ? { maxHeight } : { height: initHeight }
}

function changeHeight() {
	open = !open
}

这种方案的原理是通过设置足够大的maxHeight来实现动画的,缺点是打开状态下由于maxHeight比实际的height大得多,因此在动画的前半段时间,高度动画是卡顿住的,无法与盒子内部content的动画一致,体验不好。
如果要改善这个问题,只能通过不断减小maxHeight的值;但与此同时,当maxHeight足够小是,为了保证内容不被hidden,我们又要绕回到js计算最高高度了。所以这个方案不可行。

3.2 方案2 初始化时将盒子设置为展开状态,记住最高高度然后还原展开状态(good)

// js
const currentOpen = this.operationIsOpen;

this.operationIsOpen = true;
this.$nextTick(() => {
	const operationBlock = document.getElementsByClassName(
		  'operation-block'
	)[0];
	if (!operationBlock) return;
	this.maxHeight = operationBlock.offsetHeight;
	this.operationIsOpen = currentOpen;
});

获取了准确的maxHeight而又不用进行js计算,个人认为这是这个需求的最优解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值