实现 Vue 折叠面板组件
Posted Himmelbleu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现 Vue 折叠面板组件相关的知识,希望对你有一定的参考价值。
block 和 none 问题
一些 CSS 属性可以是动画的,也就是说,当它的值改变时,它可以以平滑的方式改变。
做折叠面板最简单的方式是改变它的 block
或 none
,这两个属性值不包含在可动画属性中。详见:CSS animated properties。所以,设置 CSS 动画(keyframes)或 transition 都是没有效果的。
JS 辅助实现
这个时候就需要借助 JS 来实现折叠面板。首先,获取折叠面板内容的高度,有了高度按照一定周期来逐步增加高度,或逐步减少高度。
<div class="l-expandable">
<div class="l-expandable__title">
<div @click="isToggled = !isToggled">
<div>
<slot name="icon" />
</div>
text
</div>
<div @click="toggle">
<i-ep-arrow-down />
</div>
</div>
<div
@click="toggle"
:class=" \'arrow-up\': !isToggled, \'arrow-down\': isToggled ">
<div class="arrow">
<i-ep-arrow-down />
</div>
</div>
</div>
setup
通过一个变量 isToggled
来判断是否折叠过面板。content
是获取面板内容的模板引用,height
是高度,对模板引用的高度进行设置。
// setup
const isToggled = ref(true);
const content = ref();
const height = ref();
// 把每一个折叠面板的高度都分成 10 份来间接性执行,执行完最后一帧之后设置 0,即不显示内容
function toggleClose()
let counter = 9;
let cHeight = height.value;
const interval = setInterval(() =>
cHeight -= height.value / 10;
content.value.style.height = `$cHeight.valuepx`;
counter--;
if (counter == 0)
content.value.style.height = `$0px`;
// 已经折叠了面板
isToggled.value = false;
clearInterval(interval);
, 10);
function toggleOpen()
let counter = 9;
let cHeight = 0;
const interval = setInterval(() =>
cHeight += height.value / 10;
content.value.style.height = `$cHeightpx`;
counter--;
if (counter == 0)
content.value.style.height = `$height.valuepx`;
// 已经打开了面板
isToggled.value = true;
clearInterval(interval);
, 10);
function toggle()
if (isToggled.value)
toggleClose();
else
toggleOpen();
// 组件内容渲染完成之后,获取模板引用对象,计算高度,并插入到 CSS 样式中
onMounted(() =>
height.value = $(content.value).height();
content.value.style.height = `$height.valuepx`;
);
CSS 动画
.l-expandable__title
border-left: 4px solid var(--el-color-primary);
.arrow
transform: scale(0, 0);
.l-expandable__title:hover .arrow
transform: scale(1, 1);
.arrow-up
animation: arrow-up-animation 0.3s ease-in;
transform: rotate(180deg);
.arrow-down
animation: arrow-down-animation 0.3s ease-in;
transform: rotate(0deg);
@keyframes arrow-up-animation
@for $index from 0 to 10
#$index * 10%
transform: rotate($index * 18deg);
@keyframes arrow-down-animation
@for $index from 0 to 10
#$index * 10%
transform: rotate(180deg - $index * 18deg);
.l-expandable__content
overflow: hidden;
transition: var(--l-transition);
实现效果
以上是关于实现 Vue 折叠面板组件的主要内容,如果未能解决你的问题,请参考以下文章
vue实现collapse折叠板动画,可设置动画时间,动画延迟等
vue.js + elementUI实现动态渲染折叠面板,以及里面的CheckBox全选
是否有可能制作一个类似面板的 React 组件,显示带有行号和折叠功能的源代码?