Skip to content

Commit 1f5801d

Browse files
feat: ✨ Siderbar 侧边栏添加before-change属性支持异步更新 (#721)
Closes: #711
1 parent 08e7d77 commit 1f5801d

4 files changed

Lines changed: 171 additions & 84 deletions

File tree

docs/component/sidebar.md

Lines changed: 111 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -67,27 +67,58 @@ function handleChange({ value, label }) {
6767
}
6868
```
6969

70+
## 异步切换
71+
72+
通过 `before-change` 属性可以在切换标签前执行特定的逻辑。它接收 `{ value, resolve }` 参数,通过 `resolve` `继续执行,resolve` 接收 1 个 boolean 参数
73+
74+
```html
75+
<wd-sidebar v-model="active" :before-change="beforeChange">
76+
<wd-sidebar-item :value="0" label="标签名称" />
77+
<wd-sidebar-item :value="1" label="标签名称" disabled />
78+
<wd-sidebar-item :value="2" label="标签名称" />
79+
</wd-sidebar>
80+
```
81+
```typescript
82+
import { useToast } from '@/uni_modules/wot-design-uni'
83+
import type { SidebarBeforeChange } from '@/uni_modules/wot-design-uni/components/wd-sidebar/types'
84+
import { ref } from 'vue'
85+
const { loading: showLoading, close: closeLoading } = useToast()
86+
87+
const toast = useToast()
88+
const active = ref<number>(1)
89+
90+
const beforeChange: SidebarBeforeChange = ({ value, resolve }) => {
91+
showLoading('切换中')
92+
setTimeout(() => {
93+
closeLoading()
94+
resolve(true)
95+
}, 2000)
96+
}
97+
```
98+
99+
70100
## 锚点用法示例
71101

72-
sidebar组件的锚点用法可以帮助用户在长页面上快速导航到特定的部分
102+
sidebar 组件的锚点用法可以帮助用户在长页面上快速导航到特定的部分
73103

74104
::: details 查看锚点用法示例
75105
::: code-group
76-
``` html [vue]
77-
<view class="wraper">
78-
<wd-sidebar v-model="active" @change="handleChange">
79-
<wd-sidebar-item v-for="(item, index) in categories" :key="index" :value="index" :label="item.label" />
80-
</wd-sidebar>
81-
<scroll-view class="content" scroll-y scroll-with-animation :scroll-top="scrollTop" :throttle="false" @scroll="onScroll">
82-
<view v-for="(item, index) in categories" :key="index" class="category">
83-
<wd-cell-group :title="item.title" border>
84-
<wd-cell v-for="(cell, index) in item.items" :key="index" :title="cell.title" :label="cell.label">
85-
<wd-icon name="github-filled" size="24px"></wd-icon>
86-
</wd-cell>
87-
</wd-cell-group>
88-
</view>
89-
</scroll-view>
106+
107+
```html [vue]
108+
<view class="wraper">
109+
<wd-sidebar v-model="active" @change="handleChange">
110+
<wd-sidebar-item v-for="(item, index) in categories" :key="index" :value="index" :label="item.label" />
111+
</wd-sidebar>
112+
<scroll-view class="content" scroll-y scroll-with-animation :scroll-top="scrollTop" :throttle="false" @scroll="onScroll">
113+
<view v-for="(item, index) in categories" :key="index" class="category">
114+
<wd-cell-group :title="item.title" border>
115+
<wd-cell v-for="(cell, index) in item.items" :key="index" :title="cell.title" :label="cell.label">
116+
<wd-icon name="github-filled" size="24px"></wd-icon>
117+
</wd-cell>
118+
</wd-cell-group>
90119
</view>
120+
</scroll-view>
121+
</view>
91122
```
92123

93124
```typescript [typescript]
@@ -179,45 +210,47 @@ function onScroll(e) {
179210
background: #fff;
180211
}
181212
```
213+
182214
:::
183215

184216
## 切换页面用法示例
185217

186-
sidebar组件在每次切换激活项时,跳转到指定的页面,且无法通过滚动导航到下一个sidebar项
218+
sidebar 组件在每次切换激活项时,跳转到指定的页面,且无法通过滚动导航到下一个 sidebar 项
187219

188220
::: details 查看切换页面用法示例
189221
::: code-group
190-
``` html [vue]
191-
<view class="wraper">
192-
<wd-sidebar v-model="active" @change="handleChange">
193-
<wd-sidebar-item
194-
v-for="(item, index) in categories"
195-
:key="index"
196-
:value="index"
197-
:label="item.label"
198-
:icon="item.icon"
199-
:disabled="item.disabled"
200-
/>
201-
</wd-sidebar>
202-
<view class="content" :style="`transform: translateY(-${active * 100}%)`">
203-
<scroll-view
204-
v-for="(item, index) in categories"
205-
:key="index"
206-
class="category"
207-
scroll-y
208-
scroll-with-animation
209-
:show-scrollbar="false"
210-
:scroll-top="scrollTop"
211-
:throttle="false"
212-
>
213-
<wd-cell-group :title="item.title" border>
214-
<wd-cell v-for="(cell, index) in item.items" :key="index" :title="cell.title" :label="cell.label">
215-
<wd-icon name="github-filled" size="24px"></wd-icon>
216-
</wd-cell>
217-
</wd-cell-group>
218-
</scroll-view>
219-
</view>
220-
</view>
222+
223+
```html [vue]
224+
<view class="wraper">
225+
<wd-sidebar v-model="active" @change="handleChange">
226+
<wd-sidebar-item
227+
v-for="(item, index) in categories"
228+
:key="index"
229+
:value="index"
230+
:label="item.label"
231+
:icon="item.icon"
232+
:disabled="item.disabled"
233+
/>
234+
</wd-sidebar>
235+
<view class="content" :style="`transform: translateY(-${active * 100}%)`">
236+
<scroll-view
237+
v-for="(item, index) in categories"
238+
:key="index"
239+
class="category"
240+
scroll-y
241+
scroll-with-animation
242+
:show-scrollbar="false"
243+
:scroll-top="scrollTop"
244+
:throttle="false"
245+
>
246+
<wd-cell-group :title="item.title" border>
247+
<wd-cell v-for="(cell, index) in item.items" :key="index" :title="cell.title" :label="cell.label">
248+
<wd-icon name="github-filled" size="24px"></wd-icon>
249+
</wd-cell>
250+
</wd-cell-group>
251+
</scroll-view>
252+
</view>
253+
</view>
221254
```
222255

223256
```typescript [typescript]
@@ -307,6 +340,7 @@ function handleChange({ value }) {
307340
height: 100%;
308341
}
309342
```
343+
310344
:::
311345

312346
## 自定义图标用法示例
@@ -315,21 +349,22 @@ function handleChange({ value }) {
315349

316350
::: details 自定义图标用法示例
317351
::: code-group
318-
``` html [vue]
319-
<view class="wraper">
320-
<wd-sidebar v-model="active" @change="handleChange">
321-
<wd-sidebar-item v-for="(item, index) in categories" :key="index" :value="index" :label="item.label" :icon="item.icon" />
322-
</wd-sidebar>
323-
<scroll-view class="content" scroll-y scroll-with-animation :scroll-top="scrollTop" :throttle="false" @scroll="onScroll">
324-
<view v-for="(item, index) in categories" :key="index" class="category">
325-
<wd-cell-group :title="item.title" border>
326-
<wd-cell v-for="(cell, index) in item.items" :key="index" :title="cell.title" :label="cell.label">
327-
<wd-icon name="github-filled" size="24px"></wd-icon>
328-
</wd-cell>
329-
</wd-cell-group>
330-
</view>
331-
</scroll-view>
352+
353+
```html [vue]
354+
<view class="wraper">
355+
<wd-sidebar v-model="active" @change="handleChange">
356+
<wd-sidebar-item v-for="(item, index) in categories" :key="index" :value="index" :label="item.label" :icon="item.icon" />
357+
</wd-sidebar>
358+
<scroll-view class="content" scroll-y scroll-with-animation :scroll-top="scrollTop" :throttle="false" @scroll="onScroll">
359+
<view v-for="(item, index) in categories" :key="index" class="category">
360+
<wd-cell-group :title="item.title" border>
361+
<wd-cell v-for="(cell, index) in item.items" :key="index" :title="cell.title" :label="cell.label">
362+
<wd-icon name="github-filled" size="24px"></wd-icon>
363+
</wd-cell>
364+
</wd-cell-group>
332365
</view>
366+
</scroll-view>
367+
</view>
333368
```
334369

335370
```typescript [typescript]
@@ -427,14 +462,15 @@ function onScroll(e) {
427462
background: #fff;
428463
}
429464
```
430-
:::
431465

466+
:::
432467

433468
## Attributes
434469

435-
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
436-
| ------------------ | ---------------- | ---------------- | ------ | ------ | -------- |
437-
| modelValue/v-model | 当前导航项的索引 | string \| number | - | 0 | 0.1.49 |
470+
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
471+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ------ | ------ | ---------------- |
472+
| modelValue/v-model | 当前导航项的索引 | string \| number | - | 0 | 0.1.49 |
473+
| before-change | 切换导航项前钩子,可以在切换标签前执行特定的逻辑,接收 { value, resolve } 参数,通过 resolve 继续执行,resolve 接收 1 个 boolean 参数 | function | - | - | $LOWEST_VERSION$ |
438474

439475
## Events
440476

@@ -457,17 +493,16 @@ function onScroll(e) {
457493

458494
## SidebarItem Attributes
459495

460-
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
461-
| -------- | ---------------------- | -------------------------- | ------ | ------ | -------- |
462-
| label | 当前选项标题 | string | - | - | 0.1.49 |
463-
| value | 当前选项的值,唯一标识 | `number \| string` | - | - | 0.1.49 |
464-
| icon | 图标 | string | - | - | 0.1.49 |
465-
| badge | 徽标属性,徽标显示值 | `number \| string \| null` | - | - | 0.1.49 |
466-
| isDot | 徽标属性,是否点状徽标 | boolean | - | false | 0.1.49 |
467-
| max | 徽标属性,徽标最大值 | number | - | 99 | 0.1.49 |
468-
| disabled | 是否禁用 | boolean | - | false | 0.1.49 |
469-
| badge-props | 自定义徽标的属性,传入的对象会被透传给 [Badge 组件的 props](/component/badge#attributes) | BadgeProps | - | - | 0.1.50 |
470-
496+
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
497+
| ----------- | ---------------------------------------------------------------------------------------- | -------------------------- | ------ | ------ | -------- |
498+
| label | 当前选项标题 | string | - | - | 0.1.49 |
499+
| value | 当前选项的值,唯一标识 | `number \| string` | - | - | 0.1.49 |
500+
| icon | 图标 | string | - | - | 0.1.49 |
501+
| badge | 徽标属性,徽标显示值 | `number \| string \| null` | - | - | 0.1.49 |
502+
| isDot | 徽标属性,是否点状徽标 | boolean | - | false | 0.1.49 |
503+
| max | 徽标属性,徽标最大值 | number | - | 99 | 0.1.49 |
504+
| disabled | 是否禁用 | boolean | - | false | 0.1.49 |
505+
| badge-props | 自定义徽标的属性,传入的对象会被透传给 [Badge 组件的 props](/component/badge#attributes) | BadgeProps | - | - | 0.1.50 |
471506

472507
## SidebarItem Slots
473508

src/pages/sidebar/Index.vue

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<!--
22
* @Author: weisheng
33
* @Date: 2023-11-06 20:08:34
4-
* @LastEditTime: 2023-11-06 20:32:06
4+
* @LastEditTime: 2024-11-18 23:27:20
55
* @LastEditors: weisheng
66
* @Description:
7-
* @FilePath: \wot-design-uni\src\pages\sidebar\Index.vue
7+
* @FilePath: /wot-design-uni/src/pages/sidebar/Index.vue
88
* 记得注释
99
-->
1010
<template>
@@ -21,7 +21,7 @@
2121
<wd-sidebar-item :value="1" label="标签名称" badge="5" />
2222
<wd-sidebar-item :value="2" label="标签名称" badge="2" :badge-props="{ type: 'warning', modelValue: 55, max: 99 }" />
2323
</wd-sidebar>
24-
<wd-sidebar v-model="active3">
24+
<wd-sidebar v-model="active3" :before-change="beforeChange">
2525
<wd-sidebar-item :value="0" label="标签名称" />
2626
<wd-sidebar-item :value="1" label="标签名称" disabled />
2727
<wd-sidebar-item :value="2" label="标签名称" />
@@ -49,12 +49,23 @@
4949
</page-wraper>
5050
</template>
5151
<script lang="ts" setup>
52+
import { useToast } from '@/uni_modules/wot-design-uni'
53+
import type { SidebarBeforeChange } from '@/uni_modules/wot-design-uni/components/wd-sidebar/types'
5254
import { ref } from 'vue'
55+
const { loading: showLoading, close: closeLoading } = useToast()
5356
5457
const active1 = ref(0)
5558
const active2 = ref(0)
5659
const active3 = ref(0)
5760
61+
const beforeChange: SidebarBeforeChange = ({ value, resolve }) => {
62+
showLoading('切换中')
63+
setTimeout(() => {
64+
closeLoading()
65+
resolve(true)
66+
}, 2000)
67+
}
68+
5869
function handleClick1() {
5970
uni.navigateTo({ url: '/pages/sidebar/demo1' })
6071
}
Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/*
22
* @Author: weisheng
33
* @Date: 2024-01-05 18:03:27
4-
* @LastEditTime: 2024-03-18 15:52:37
4+
* @LastEditTime: 2024-11-18 23:27:55
55
* @LastEditors: weisheng
66
* @Description:
7-
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-sidebar\types.ts
7+
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-sidebar/types.ts
88
* 记得注释
99
*/
10-
import { type ExtractPropTypes, type InjectionKey } from 'vue'
10+
import { type ExtractPropTypes, type InjectionKey, type PropType } from 'vue'
1111
import { baseProps, makeNumericProp } from '../common/props'
1212

1313
export type SidebarProvide = {
@@ -17,12 +17,31 @@ export type SidebarProvide = {
1717

1818
export const SIDEBAR_KEY: InjectionKey<SidebarProvide> = Symbol('wd-sidebar')
1919

20+
/**
21+
* Sidebar切换前的选项接口
22+
*/
23+
export type SidebarBeforeChangeOption = {
24+
// 目标值
25+
value: number | string
26+
resolve: (pass: boolean) => void
27+
}
28+
29+
/**
30+
* Sidebar切换前的钩子函数类型
31+
* @param option 切换选项
32+
*/
33+
export type SidebarBeforeChange = (option: SidebarBeforeChangeOption) => void
34+
2035
export const sidebarProps = {
2136
...baseProps,
2237
/**
2338
* 当前导航项的索引
2439
*/
25-
modelValue: makeNumericProp(0)
40+
modelValue: makeNumericProp(0),
41+
/**
42+
* 在改变前执行的函数
43+
*/
44+
beforeChange: Function as PropType<SidebarBeforeChange>
2645
}
2746

2847
export type SidebarProps = ExtractPropTypes<typeof sidebarProps>

src/uni_modules/wot-design-uni/components/wd-sidebar/wd-sidebar.vue

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export default {
1717
</script>
1818

1919
<script lang="ts" setup>
20+
import { isFunction } from '../common/util'
2021
import { useChildren } from '../composables/useChildren'
2122
import { SIDEBAR_KEY, sidebarProps } from './types'
2223
@@ -28,9 +29,30 @@ linkChildren({ props, setChange })
2829
2930
/**
3031
* 子项状态变更
31-
* @param child 子项
32+
* @param value 目标值
33+
* @param label 目标值标题
3234
*/
3335
function setChange(value: number | string, label: string) {
36+
if (isFunction(props.beforeChange)) {
37+
props.beforeChange({
38+
value: value,
39+
resolve: (pass: boolean) => {
40+
if (pass) {
41+
updateValue(value, label)
42+
}
43+
}
44+
})
45+
} else {
46+
updateValue(value, label)
47+
}
48+
}
49+
50+
/**
51+
* 更新选中状态
52+
* @param value 目标值
53+
* @param label 目标值标题
54+
*/
55+
function updateValue(value: number | string, label: string) {
3456
emit('update:modelValue', value)
3557
emit('change', { value, label })
3658
}

0 commit comments

Comments
 (0)