Skip to content

Commit a5ce5dd

Browse files
feat: ✨ Collapse 折叠面板组件支持嵌套使用 (#521)
Closes: #503
1 parent cd96d25 commit a5ce5dd

File tree

3 files changed

+90
-46
lines changed

3 files changed

+90
-46
lines changed

src/pages/collapse/Index.vue

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<template>
22
<page-wraper>
33
<wd-toast></wd-toast>
4-
<demo-block title="基础用法" transparent>
5-
<wd-button @click="collapse?.toggleAll()">toggleAll</wd-button>
64

5+
<demo-block title="toggleAll" transparent>
6+
<wd-button @click="collapse?.toggleAll()">toggleAll</wd-button>
7+
</demo-block>
8+
<demo-block title="基础用法" transparent>
79
<wd-collapse ref="collapse" v-model="value1" @change="handleChange1">
810
<wd-collapse-item
911
v-for="(item, index) in itemList"
@@ -55,6 +57,19 @@
5557
<wd-collapse-item title="标签3" name="item3">这是一条简单的示例文字。</wd-collapse-item>
5658
</wd-collapse>
5759
</demo-block>
60+
61+
<demo-block title="嵌套" transparent>
62+
<wd-collapse v-model="collapseRoot" @change="handleChange1">
63+
<wd-collapse-item v-for="item in 5" :key="item" :title="`标签${item}`" :name="`${item}`">
64+
<wd-collapse v-model="collapseList[item - 1]">
65+
<wd-collapse-item v-for="(item, index) in itemList" :key="index" :title="item.title" :name="item.name">
66+
{{ item.body }}
67+
</wd-collapse-item>
68+
</wd-collapse>
69+
</wd-collapse-item>
70+
</wd-collapse>
71+
</demo-block>
72+
5873
<demo-block title="查看更多" transparent>
5974
<wd-collapse viewmore v-model="value4" @change="handleChange4">
6075
这是一条简单的示例文字。这是一条简单的示例文字。这是一条简单的示例文字。这是一条简单的示例文字。这是一条简单的示例文字。这是一条简单的示例文字。这是一条简单的示例文字。这是一条简单的示例文字。
@@ -120,7 +135,33 @@ const value6 = ref<boolean>(false)
120135
const value7 = ref<string[]>(['item1'])
121136
const desc7 = '如订单处于暂停状态,进入“我的订单”页面,找到要取消的订单,点击“取消订单”按钮;选择订单取消原因后,点击“下一步”提交申请即可。'
122137
const accordion = ref<boolean>(true)
123-
const name = ref<string>('item1')
138+
139+
const collapseRoot = ref<string[]>(['0'])
140+
const collapseList = ref<Array<string[]>>([['item1'], ['item2'], ['item3'], ['item4'], ['item5']])
141+
142+
function handleChange1({ value }: any) {
143+
console.log(value)
144+
}
145+
function handleChange2({ value }: any) {
146+
console.log(value)
147+
}
148+
function handleChange3({ value }: any) {
149+
console.log(value)
150+
}
151+
function handleChange4({ value }: any) {
152+
console.log(value)
153+
}
154+
function handleChange5({ value }: any) {
155+
console.log(value)
156+
}
157+
function handleChange6({ value }: any) {
158+
console.log(value)
159+
}
160+
function handleChange7({ value }: any) {
161+
console.log(value)
162+
}
163+
164+
/**
124165
125166
function handleChange1({ value }: any) {
126167
console.log(value)

src/uni_modules/wot-design-uni/components/wd-collapse-item/index.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060

6161
@include e(wrapper) {
6262
position: relative;
63-
transition: height 0.3s ease-in-out;
6463
overflow: hidden;
6564
will-change: height;
6665
}

src/uni_modules/wot-design-uni/components/wd-collapse-item/wd-collapse-item.vue

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<wd-icon name="arrow-down" :custom-class="`wd-collapse-item__arrow ${expanded ? 'is-retract' : ''}`" />
77
</slot>
88
</view>
9-
<view class="wd-collapse-item__wrapper" :style="contentStyle">
10-
<view class="wd-collapse-item__body">
9+
<view class="wd-collapse-item__wrapper" :style="contentStyle" @transitionend="handleTransitionEnd">
10+
<view class="wd-collapse-item__body" :id="collapseId">
1111
<slot />
1212
</view>
1313
</view>
@@ -25,23 +25,21 @@ export default {
2525
</script>
2626

2727
<script lang="ts" setup>
28-
import { computed, getCurrentInstance, onMounted, ref, watch } from 'vue'
29-
import { getRect, isArray, isDef, isPromise, objToStyle } from '../common/util'
28+
import { computed, getCurrentInstance, onMounted, ref, watch, type CSSProperties } from 'vue'
29+
import { addUnit, getRect, isArray, isDef, isPromise, objToStyle, requestAnimationFrame, uuid } from '../common/util'
3030
import { useParent } from '../composables/useParent'
3131
import { COLLAPSE_KEY } from '../wd-collapse/types'
3232
import { collapseItemProps, type CollapseItemExpose } from './types'
3333
34-
const $body = '.wd-collapse-item__body'
34+
const collapseId = ref<string>(`collapseId${uuid()}`)
3535
3636
const props = defineProps(collapseItemProps)
3737
3838
const { parent: collapse, index } = useParent(COLLAPSE_KEY)
3939
4040
const height = ref<string | number>('')
41-
41+
const inited = ref<boolean>(false)
4242
const expanded = ref<boolean>(false)
43-
44-
const transD = ref<string>('0.3s')
4543
const { proxy } = getCurrentInstance() as any
4644
4745
/**
@@ -55,9 +53,14 @@ const isFirst = computed(() => {
5553
* 容器样式,(动画)
5654
*/
5755
const contentStyle = computed(() => {
58-
let style: Record<string, string> = {
59-
height: expanded.value ? height.value + 'px' : '0px',
60-
'transition-duration': transD.value
56+
const style: CSSProperties = {}
57+
if (inited.value) {
58+
style.transition = 'height 0.3s ease-in-out'
59+
}
60+
if (!expanded.value) {
61+
style.height = '0px'
62+
} else if (height.value) {
63+
style.height = addUnit(height.value)
6164
}
6265
return objToStyle(style)
6366
})
@@ -72,21 +75,11 @@ const selected = computed(() => {
7275
7376
watch(
7477
() => selected.value,
75-
(newVal) => {
76-
const name = props.name
77-
if (isDef(newVal)) {
78-
if (typeof newVal === 'string' && newVal === name) {
79-
doResetHeight($body)
80-
expanded.value = true
81-
} else if (isArray(newVal) && newVal.indexOf(name as string) >= 0) {
82-
doResetHeight($body)
83-
expanded.value = true
84-
} else {
85-
expanded.value = false
86-
}
87-
} else {
88-
expanded.value = false
78+
() => {
79+
if (!inited.value) {
80+
return
8981
}
82+
updateExpend()
9083
},
9184
{
9285
deep: true,
@@ -95,29 +88,40 @@ watch(
9588
)
9689
9790
onMounted(() => {
98-
init()
91+
updateExpend()
9992
})
10093
101-
/**
102-
* 初始化将组件信息注入父组件
103-
*/
104-
function init() {
105-
doResetHeight($body)
106-
}
107-
108-
/**
109-
* 控制折叠面板滚动
110-
* @param {String} select 选择器名称
111-
* @param {Boolean} firstRender 是否首次渲染
112-
*/
113-
function doResetHeight(select: string) {
114-
getRect(select, false, proxy).then((rect) => {
115-
if (!rect) return
94+
function updateExpend() {
95+
return getRect(`#${collapseId.value}`, false, proxy).then((rect) => {
11696
const { height: rectHeight } = rect
117-
height.value = Number(rectHeight)
97+
height.value = isDef(rectHeight) ? Number(rectHeight) : ''
98+
const name = props.name
99+
requestAnimationFrame(() => {
100+
if (isDef(selected.value)) {
101+
if (
102+
(typeof selected.value === 'string' && selected.value === name) ||
103+
(isArray(selected.value) && selected.value.indexOf(name as string) >= 0)
104+
) {
105+
expanded.value = true
106+
} else {
107+
expanded.value = false
108+
}
109+
} else {
110+
expanded.value = false
111+
}
112+
if (!inited.value) {
113+
inited.value = true
114+
}
115+
})
118116
})
119117
}
120118
119+
function handleTransitionEnd() {
120+
if (expanded.value) {
121+
height.value = ''
122+
}
123+
}
124+
121125
// 点击子项
122126
function handleClick() {
123127
if (props.disabled) return

0 commit comments

Comments
 (0)