cl-collapse.uvue 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <template>
  2. <view class="cl-collapse" :style="{ height: `${height}px` }">
  3. <view class="cl-collapse__content" :class="[pt.className]">
  4. <slot></slot>
  5. </view>
  6. </view>
  7. </template>
  8. <script setup lang="ts">
  9. import { getCurrentInstance, ref, computed, watch } from "vue";
  10. import { parsePt } from "@/cool";
  11. defineOptions({
  12. name: "cl-collapse"
  13. });
  14. // 定义组件属性
  15. const props = defineProps({
  16. // 透传样式配置
  17. pt: {
  18. type: Object,
  19. default: () => ({})
  20. },
  21. // 折叠状态值
  22. modelValue: {
  23. type: Boolean,
  24. default: false
  25. }
  26. });
  27. // 获取组件实例
  28. const { proxy } = getCurrentInstance()!;
  29. // 透传样式类型定义
  30. type PassThrough = {
  31. className?: string;
  32. };
  33. // 解析透传样式
  34. const pt = computed(() => parsePt<PassThrough>(props.pt));
  35. // 折叠展开状态
  36. const isOpened = ref(false);
  37. // 内容高度
  38. const height = ref(0);
  39. /**
  40. * 显示折叠内容
  41. */
  42. function show() {
  43. isOpened.value = true;
  44. // 获取内容区域高度
  45. uni.createSelectorQuery()
  46. .in(proxy)
  47. .select(".cl-collapse__content")
  48. .boundingClientRect((node) => {
  49. height.value = (node as NodeInfo).height ?? 0;
  50. })
  51. .exec();
  52. }
  53. /**
  54. * 隐藏折叠内容
  55. */
  56. function hide() {
  57. isOpened.value = false;
  58. height.value = 0;
  59. }
  60. /**
  61. * 切换折叠状态
  62. */
  63. function toggle() {
  64. if (isOpened.value) {
  65. hide();
  66. } else {
  67. show();
  68. }
  69. }
  70. // 监听折叠状态变化
  71. watch(
  72. computed(() => props.modelValue),
  73. (val: boolean) => {
  74. if (val) {
  75. show();
  76. } else {
  77. hide();
  78. }
  79. }
  80. );
  81. defineExpose({
  82. show,
  83. hide,
  84. toggle
  85. });
  86. </script>
  87. <style lang="scss" scoped>
  88. .cl-collapse {
  89. @apply relative;
  90. transition-property: height;
  91. transition-duration: 0.2s;
  92. &__content {
  93. @apply absolute top-0 left-0 w-full pt-3;
  94. }
  95. }
  96. </style>