应用场景
-
当列表内容很长时,需要滑倒最底部才能查看下一条数据,这时可以使用该组件的交互来优化使用体验。收起当前一条,继续展开查看下一条数据。
image.png
组件思路
判断同时满足以下两个条件时,悬浮展示收起按钮
- 展开的内容的盒子的左上角坐标的Y值即top + 收起按钮的高度 <= 当前浏览器窗口的可视区域高度clientHeight
-
展开的内容的盒子的右下角坐标的Y值即bottom > 当前浏览器窗口的可视区域高度clientHeight
image.png
<template>
<div class="collapse-item">
<div class="source">
<slot name="source"></slot>
</div>
<div class="collapse-panel">
<div class="panel">
<div
class="panel-content"
ref="panel-content"
:style="{ '--panelMinHeight': minHeight + 'px', '--panelHeight': panelHeight }"
:class="isExpanded ? 'active' : ''"
>
<slot></slot>
</div>
<div
class="expand-btn height-96 flex-center"
@click="togglePanel"
:class="{ 'is-fixed': fixedControl }"
v-if="isExpandShow"
>
<span class="color-main">{{ isExpanded ? "收起" : "展开" }}</span>
<img
src="@/assets/databoard/arrow-fold.png"
class="expand-icon width-24 height-22 m-l-10"
:class="!isExpanded ? '' : 'icon-reverse'"
/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "CollapseItem",
props: {
minHeight: {
type: Number,
default: 0
},
isExpandShow: {
type: Boolean,
default: false
}
},
data() {
return {
isExpanded: false,
panelHeight: 0, // 展开内容高度
fixedControl: false, // 固定收起按钮控制
scrollTop: 0 // 展开之前的滚动位置
};
},
watch: {
isExpanded(val) {
if (!val) {
this.fixedControl = false;
this.removeScrollHandler();
window.scrollTo({
top: this.scrollTop
});
return;
}
const timer = setTimeout(() => {
window.addEventListener("scroll", this.scrollHandler);
this.scrollHandler();
clearTimeout(timer);
}, 100);
}
},
methods: {
// 切换展开收起状态
togglePanel() {
if (!this.panelHeight) {
const panel = this.$refs["panel-content"];
const panelHeight = panel.scrollHeight;
this.panelHeight = panelHeight + "px";
}
this.isExpanded = !this.isExpanded;
this.$nextTick(() => {
this.scrollTop = document.documentElement.scrollTop;
});
},
// 监听滚动事件,控制收起按钮展示和隐藏
scrollHandler() {
const { top, bottom } = this.$refs["panel-content"].getBoundingClientRect();
const clientHeight = document.documentElement.clientHeight;
this.fixedControl = bottom > clientHeight && top + 48 <= clientHeight;
},
// 移除滚动事件
removeScrollHandler() {
window.removeEventListener("scroll", this.scrollHandler);
}
},
beforeDestroy() {
this.removeScrollHandler();
}
};
</script>
<style lang="less" scoped>
.collapse-panel {
.panel-content {
width: 100%;
height: var(--panelMinHeight);
overflow-y: hidden;
overflow-x: visible;
transition: height 0.2s;
}
.active {
height: var(--panelHeight);
}
.expand-btn {
.expand-icon {
transition: all 0.2s;
}
.icon-reverse {
transform: rotate(180deg);
}
}
.is-fixed {
position: fixed;
bottom: 0px;
background: #fff;
width: 100%;
left: 0;
box-shadow: 0px -8px 24px 1px rgba(0, 0, 0, 0.1);
}
}
</style>
网友评论