Files
WAI_Project_UNIX/uni_modules/cool-ui/components/cl-collapse/cl-collapse.uvue

113 lines
1.7 KiB
Plaintext
Raw Normal View History

2025-07-21 16:47:04 +08:00
<template>
<view class="cl-collapse" :style="{ height: `${height}px` }">
<view class="cl-collapse__content" :class="[pt.className]">
<slot></slot>
</view>
</view>
</template>
<script setup lang="ts">
import { getCurrentInstance, ref, computed, watch } from "vue";
import { parsePt } from "@/cool";
defineOptions({
name: "cl-collapse"
});
// 定义组件属性
const props = defineProps({
// 透传样式配置
pt: {
type: Object,
default: () => ({})
},
// 折叠状态值
modelValue: {
type: Boolean,
default: false
}
});
// 获取组件实例
const { proxy } = getCurrentInstance()!;
// 透传样式类型定义
type PassThrough = {
className?: string;
};
// 解析透传样式
const pt = computed(() => parsePt<PassThrough>(props.pt));
// 折叠展开状态
const isOpened = ref(false);
// 内容高度
const height = ref(0);
/**
* 显示折叠内容
*/
function show() {
isOpened.value = true;
// 获取内容区域高度
uni.createSelectorQuery()
.in(proxy)
.select(".cl-collapse__content")
.boundingClientRect((node) => {
height.value = (node as NodeInfo).height ?? 0;
})
.exec();
}
/**
* 隐藏折叠内容
*/
function hide() {
isOpened.value = false;
height.value = 0;
}
/**
* 切换折叠状态
*/
function toggle() {
if (isOpened.value) {
hide();
} else {
show();
}
}
// 监听折叠状态变化
watch(
computed(() => props.modelValue),
(val: boolean) => {
if (val) {
show();
} else {
hide();
}
}
);
defineExpose({
show,
hide,
toggle
});
</script>
<style lang="scss" scoped>
.cl-collapse {
@apply relative;
transition-property: height;
transition-duration: 0.2s;
&__content {
@apply absolute top-0 left-0 w-full pt-3;
}
}
</style>