Collapse组件

需求分析

折叠面板组件,一般来说由两部分组成,它们分别是CollapseCollapseItem。现在我们来想一想,它们可能会有哪些属性和方法。

Collapse

属性:

  • model-value / v-model:当前活动面板,在手风琴模式下是 string 类型,在其他模式下是 array,默认值是一个空数组。
  • accordion:是否手风琴模式,是一个 boolean 类型。

事件:

  • change:切换当前活动面板,参数在手风琴模式下是 string,在其他模式下是 array
  • update:modelValue:实现 v-model 要用到

插槽:

  • default:默认插槽,自定义默认内容

CollapseItem

属性:

  • name:唯一标识符,类型是 string 或者 number
  • title:面板的标题,类型是 string
  • disabled:是否禁用,类型是 boolean
    事件:

插槽:

  • title:具名插槽,CollapseItem 的标题
  • default: 默认插槽,CollapseItem 的内容

代码实现

定义类型文件
书写 Collapse 组件骨架和交互
书写 CollapseItem 组件骨架和交互

添加动画使切换更加平滑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<Transition name="slide" v-on="transitionEvents">
<div class="tm-collapse-item__wrapper" v-show="isActive">
<div class="tm-collapse-item__content" :id="`item-content-${name}`">
<slot></slot>
</div>
</div>
</Transition>
<script>
const transitionEvents: Record<string, (el: HTMLElement) => void> = {
beforeEnter(el) {
el.style.height = '0px'
el.style.overflow = 'hidden'
},
enter(el) {
el.style.height = `${el.scrollHeight}px`
},
afterEnter(el) {
el.style.height = ''
el.style.overflow = ''
},
beforeLeave(el) {
el.style.height = `${el.scrollHeight}px`
el.style.overflow = 'hidden'
},
leave(el) {
el.style.height = '0px'
},
afterLeave(el) {
el.style.height = ''
el.style.overflow = ''
}
}
</script>
<style>
.slide-enter-active,
.slide-leave-active {
transition: height 0.3s;
}
</style>

引用组件并使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<script setup lang="ts">
import { ref } from 'vue'
import Collapse from './components/Collapse/Collapse.vue'
import Item from './components/Collapse/CollapseItem.vue'

const openedValue = ref([1])

const handleChange = (val) => {
console.log('🚀 ~ handleChange ~ val:', val)
}
</script>

<template>
<Collapse v-model="openedValue" @change="handleChange">
<Item :name="1" title="Title A">
<h1>headline title</h1>
<div>this is content a aaa</div>
</Item>
<Item :name="2" title="Title B">
<div>this is bbbbb test</div>
</Item>
<Item :name="3" title="Disabled Title" disabled>
<div>this is cccc test</div>
</Item>
</Collapse>
{{ openedValue }}
</template>