Skip to content

Commit 9f318bd

Browse files
feat: ✨ 优化Toast、Message和Notify组件的函数式调用方案 (#696)
解决当前页面存在多次使用useXX时仅最后一次生效的问题
1 parent deeb45d commit 9f318bd

File tree

8 files changed

+72
-64
lines changed

8 files changed

+72
-64
lines changed

src/uni_modules/wot-design-uni/components/wd-message-box/index.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
/*
22
* @Author: weisheng
33
* @Date: 2022-12-14 17:33:21
4-
* @LastEditTime: 2024-08-17 18:18:16
4+
* @LastEditTime: 2024-11-05 23:15:31
55
* @LastEditors: weisheng
66
* @Description:
7-
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-message-box/index.ts
7+
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-message-box\index.ts
88
* 记得注释
99
*/
10-
import { provide, ref } from 'vue'
10+
import { inject, provide, ref } from 'vue'
1111
import type { Message, MessageOptions, MessageResult, MessageType } from './types'
1212
import { deepMerge } from '../common/util'
1313

14-
/**
15-
* useMessage 用到的key
16-
*
17-
* @internal
18-
*/
19-
export const messageDefaultOptionKey = '__MESSAGE_OPTION__'
14+
const messageDefaultOptionKey = '__MESSAGE_OPTION__'
15+
16+
const None = Symbol('None')
2017

2118
// 默认模板
2219
export const defaultOptions: MessageOptions = {
@@ -36,9 +33,12 @@ export const defaultOptions: MessageOptions = {
3633
}
3734

3835
export function useMessage(selector: string = ''): Message {
39-
const messageOption = ref<MessageOptions>(defaultOptions) // Message选项
4036
const messageOptionKey = selector ? messageDefaultOptionKey + selector : messageDefaultOptionKey
41-
provide(messageOptionKey, messageOption)
37+
const messageOption = inject(messageOptionKey, ref<MessageOptions | typeof None>(None)) // Message选项
38+
if (messageOption.value === None) {
39+
messageOption.value = defaultOptions
40+
provide(messageOptionKey, messageOption)
41+
}
4242

4343
const createMethod = (type: MessageType) => {
4444
// 优先级:options->MessageOptions->defaultOptions
@@ -77,7 +77,9 @@ export function useMessage(selector: string = ''): Message {
7777
const prompt = createMethod('prompt')
7878

7979
const close = () => {
80-
messageOption.value.show = false
80+
if (messageOption.value !== None) {
81+
messageOption.value.show = false
82+
}
8183
}
8284
return {
8385
show,
@@ -87,3 +89,7 @@ export function useMessage(selector: string = ''): Message {
8789
close
8890
}
8991
}
92+
93+
export const getMessageDefaultOptionKey = (selector: string) => {
94+
return selector ? `${messageDefaultOptionKey}${selector}` : messageDefaultOptionKey
95+
}

src/uni_modules/wot-design-uni/components/wd-message-box/types.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/*
22
* @Author: weisheng
33
* @Date: 2024-04-08 22:34:01
4-
* @LastEditTime: 2024-09-23 15:59:04
4+
* @LastEditTime: 2024-11-05 23:17:06
55
* @LastEditors: weisheng
66
* @Description:
77
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-message-box\types.ts
88
* 记得注释
99
*/
10-
import { baseProps } from '../common/props'
10+
import { baseProps, makeStringProp } from '../common/props'
1111
import { type InputType } from '../wd-input/types'
1212

1313
export type MessageType = 'alert' | 'confirm' | 'prompt'
@@ -113,5 +113,8 @@ export interface Message {
113113

114114
export const messageBoxProps = {
115115
...baseProps,
116-
selector: String
116+
/**
117+
* 指定唯一标识
118+
*/
119+
selector: makeStringProp('')
117120
}

src/uni_modules/wot-design-uni/components/wd-message-box/wd-message-box.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ import {
6161
type MessageResult,
6262
type MessageType
6363
} from './types'
64-
import { defaultOptions, messageDefaultOptionKey } from '.'
64+
import { defaultOptions, getMessageDefaultOptionKey } from '.'
6565
import { isDef, isFunction } from '../common/util'
6666
import { useTranslate } from '../composables/useTranslate'
6767
import { type InputType } from '../wd-input/types'
@@ -78,7 +78,7 @@ const bodyClass = computed(() => {
7878
return `wd-message-box__body ${!title.value ? 'is-no-title' : ''} ${type.value === 'prompt' ? 'is-prompt' : ''}`
7979
})
8080
81-
const messageOptionKey = props.selector ? messageDefaultOptionKey + props.selector : messageDefaultOptionKey
81+
const messageOptionKey = getMessageDefaultOptionKey(props.selector)
8282
const messageOption = inject(messageOptionKey, ref<MessageOptions>(defaultOptions)) // message选项
8383
8484
/**

src/uni_modules/wot-design-uni/components/wd-notify/index.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,40 @@
1-
import { provide, reactive } from 'vue'
1+
import { inject, provide, reactive, ref } from 'vue'
22
import type { NotifyProps } from './types'
33
import { deepMerge, isString } from '../common/util'
44

55
let timer: ReturnType<typeof setTimeout>
66
let currentOptions = getDefaultOptions()
77
const notifyDefaultOptionKey = '__NOTIFY_OPTION__'
8+
const None = Symbol('None')
89
export const setNotifyDefaultOptions = (options: NotifyProps) => {
910
currentOptions = deepMerge(currentOptions, options) as NotifyProps
1011
}
1112
export const resetNotifyDefaultOptions = () => {
1213
currentOptions = getDefaultOptions()
1314
}
1415
export const useNotify = (selector: string = '') => {
15-
const notifyOption = reactive<NotifyProps>(currentOptions)
16+
const notifyOptionKey = getNotifyOptionKey(selector)
17+
18+
const notifyOption = inject(notifyOptionKey, ref<NotifyProps | typeof None>(None))
19+
if (notifyOption.value === None) {
20+
notifyOption.value = currentOptions
21+
provide(notifyOptionKey, notifyOption)
22+
}
1623
const showNotify = (option: NotifyProps | string) => {
1724
const options = deepMerge(currentOptions, isString(option) ? { message: option } : option) as NotifyProps
18-
19-
Object.assign(notifyOption, options, { visible: true })
20-
if (notifyOption.duration && notifyOption.duration > 0) {
25+
notifyOption.value = deepMerge(options, { visible: true })
26+
if (notifyOption.value.duration && notifyOption.value.duration > 0) {
2127
timer && clearTimeout(timer)
2228
timer = setTimeout(() => closeNotify(), options.duration)
2329
}
2430
}
2531
const closeNotify = () => {
2632
timer && clearTimeout(timer)
27-
notifyOption.visible = false
33+
if (notifyOption.value !== None) {
34+
notifyOption.value.visible = false
35+
}
2836
}
2937

30-
// provide
31-
provide(getNotifyOptionKey(selector), notifyOption)
32-
3338
return {
3439
showNotify,
3540
closeNotify

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

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,18 @@
1616
</template>
1717
<script lang="ts">
1818
export default {
19-
// #ifdef H5
2019
name: 'wd-notify',
21-
// #endif
22-
options: { virtualHost: true, addGlobalClass: true, styleIsolation: 'shared' }
20+
options: {
21+
virtualHost: true,
22+
addGlobalClass: true,
23+
styleIsolation: 'shared'
24+
}
2325
}
2426
</script>
2527

2628
<script lang="ts" setup>
2729
import wdPopup from '../wd-popup/wd-popup.vue'
28-
import { inject, computed, watch } from 'vue'
30+
import { inject, computed, watch, ref } from 'vue'
2931
import { notifyProps, type NotifyProps } from './types'
3032
import { getNotifyOptionKey } from '.'
3133
import { addUnit, isFunction } from '../common/util'
@@ -37,10 +39,10 @@ const emits = defineEmits<{
3739
(e: 'closed'): void
3840
(e: 'opened'): void
3941
}>()
40-
const state = inject<NotifyProps>(getNotifyOptionKey(props.selector), props)
42+
const state = inject(getNotifyOptionKey(props.selector), ref<NotifyProps>(props))
4143
4244
const customStyle = computed(() => {
43-
const { safeHeight, position } = state
45+
const { safeHeight, position } = state.value
4446
let customStyle: string = ''
4547
switch (position) {
4648
case 'top':
@@ -56,21 +58,24 @@ const customStyle = computed(() => {
5658
})
5759
5860
const onClick = (event: MouseEvent) => {
59-
if (isFunction(state.onClick)) return state.onClick(event)
61+
if (isFunction(state.value.onClick)) return state.value.onClick(event)
6062
emits('click', event)
6163
}
6264
const onClosed = () => {
63-
if (isFunction(state.onClosed)) return state.onClosed()
65+
if (isFunction(state.value.onClosed)) return state.value.onClosed()
6466
emits('closed')
6567
}
6668
const onOpened = () => {
67-
if (isFunction(state.onOpened)) return state.onOpened()
69+
if (isFunction(state.value.onOpened)) return state.value.onOpened()
6870
emits('opened')
6971
}
7072
7173
watch(
72-
() => state.visible,
73-
(visible) => emits('update:visible', visible as boolean)
74+
() => state.value.visible,
75+
(visible) => {
76+
emits('update:visible', visible as boolean)
77+
},
78+
{ deep: true }
7479
)
7580
</script>
7681

src/uni_modules/wot-design-uni/components/wd-toast/index.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,11 @@
1-
/*
2-
* @Author: weisheng
3-
* @Date: 2024-03-29 13:29:57
4-
* @LastEditTime: 2024-07-18 23:16:16
5-
* @LastEditors: weisheng
6-
* @Description:
7-
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-toast/index.ts
8-
* 记得注释
9-
*/
10-
import { provide, ref } from 'vue'
1+
import { inject, provide, ref } from 'vue'
112
import type { Toast, ToastOptions } from './types'
123
import { deepMerge } from '../common/util'
134

145
/**
156
* useToast 用到的key
16-
*
17-
* @internal
187
*/
19-
export const toastDefaultOptionKey = '__TOAST_OPTION__'
8+
const toastDefaultOptionKey = '__TOAST_OPTION__'
209

2110
// 默认模板
2211
export const defaultOptions: ToastOptions = {
@@ -30,11 +19,16 @@ export const defaultOptions: ToastOptions = {
3019
zIndex: 100
3120
}
3221

22+
const None = Symbol('None')
23+
3324
export function useToast(selector: string = ''): Toast {
25+
const toastOptionKey = getToastOptionKey(selector)
26+
const toastOption = inject(toastOptionKey, ref<ToastOptions | typeof None>(None)) // toast选项
27+
if (toastOption.value === None) {
28+
toastOption.value = defaultOptions
29+
provide(toastOptionKey, toastOption)
30+
}
3431
let timer: ReturnType<typeof setTimeout> | null = null
35-
const toastOption = ref<ToastOptions>(defaultOptions) // Toast选项
36-
const toastOptionKey = selector ? toastDefaultOptionKey + selector : toastDefaultOptionKey
37-
provide(toastOptionKey, toastOption)
3832

3933
const createMethod = (toastOptions: ToastOptions) => {
4034
// 优先级:options->toastOptions->defaultOptions
@@ -85,6 +79,10 @@ export function useToast(selector: string = ''): Toast {
8579
}
8680
}
8781

82+
export const getToastOptionKey = (selector: string) => {
83+
return selector ? `${toastDefaultOptionKey}${selector}` : toastDefaultOptionKey
84+
}
85+
8886
export const toastIcon = {
8987
success() {
9088
return '<svg width="42px" height="42px" viewBox="0 0 42 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>成功</title><desc>Created with Sketch.</desc><defs><filter x="-63.2%" y="-80.0%" width="226.3%" height="260.0%" filterUnits="objectBoundingBox" id="filter-1"><feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset><feGaussianBlur stdDeviation="2" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur><feColorMatrix values="0 0 0 0 0.122733141 0 0 0 0 0.710852582 0 0 0 0 0.514812768 0 0 0 1 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix><feMerge><feMergeNode in="shadowMatrixOuter1"></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode></feMerge></filter><rect id="path-2" x="3.4176226" y="5.81442199" width="3" height="8.5" rx="1.5"></rect><linearGradient x1="50%" y1="0.126649064%" x2="50%" y2="100%" id="linearGradient-4"><stop stop-color="#ACFFBD" stop-opacity="0.208123907" offset="0%"></stop><stop stop-color="#10B87C" offset="100%"></stop></linearGradient></defs><g id="规范" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="反馈-轻提示" transform="translate(-388.000000, -538.000000)"><g id="成功" transform="translate(388.000000, 538.000000)"><circle id="Oval" fill="#34D19D" opacity="0.400000006" cx="21" cy="21" r="20"></circle><circle id="Oval" fill="#34D19D" cx="21" cy="21" r="16"></circle><g id="Group-6" filter="url(#filter-1)" transform="translate(11.500000, 14.000000)"><mask id="mask-3" fill="white"><use xlink:href="#path-2"></use></mask><use id="Rectangle-Copy-24" fill="#C4FFEB" transform="translate(4.917623, 10.064422) rotate(-45.000000) translate(-4.917623, -10.064422) " xlink:href="#path-2"></use><rect id="Rectangle" fill="url(#linearGradient-4)" mask="url(#mask-3)" transform="translate(6.215869, 11.372277) rotate(-45.000000) translate(-6.215869, -11.372277) " x="4.71586891" y="9.52269089" width="3" height="3.69917136"></rect><rect id="Rectangle" fill="#FFFFFF" transform="translate(11.636236, 7.232744) scale(1, -1) rotate(-45.000000) translate(-11.636236, -7.232744) " x="10.1362361" y="-1.02185365" width="3" height="16.5091951" rx="1.5"></rect></g></g></g></g></svg>'

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,11 @@ import wdTransition from '../wd-transition/wd-transition.vue'
3838
3939
import { computed, inject, onBeforeMount, ref, watch, type CSSProperties } from 'vue'
4040
import base64 from '../common/base64'
41-
import { defaultOptions, toastDefaultOptionKey, toastIcon } from '.'
41+
import { defaultOptions, getToastOptionKey, toastIcon } from '.'
4242
import { toastProps, type ToastLoadingType, type ToastOptions } from './types'
4343
import { addUnit, isDef, isFunction, objToStyle } from '../common/util'
4444
4545
const props = defineProps(toastProps)
46-
4746
const iconName = ref<string>('') // 图标类型
4847
const msg = ref<string>('') // 消息内容
4948
const position = ref<string>('middle')
@@ -62,7 +61,7 @@ let opened: (() => void) | null = null
6261
6362
let closed: (() => void) | null = null
6463
65-
const toastOptionKey = props.selector ? toastDefaultOptionKey + props.selector : toastDefaultOptionKey
64+
const toastOptionKey = getToastOptionKey(props.selector)
6665
const toastOption = inject(toastOptionKey, ref<ToastOptions>(defaultOptions)) // toast选项
6766
6867
// 监听options变化展示

src/uni_modules/wot-design-uni/index.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,15 @@
88
* 记得注释
99
*/
1010

11-
// Toast
1211
export { useToast } from './components/wd-toast'
13-
// Messageb
1412
export { useMessage } from './components/wd-message-box'
15-
16-
// useQueue
1713
export { useQueue } from './components/composables/useQueue'
18-
19-
// Notify
2014
export * from './components/wd-notify'
2115

2216
export { dayjs } from './components/common/dayjs'
2317

2418
export * as CommonUtil from './components/common/util'
25-
2619
export * as clickOut from './components/common/clickoutside'
2720

2821
export * from './locale'
29-
3022
export type { ConfigProviderThemeVars } from './components/wd-config-provider/types'

0 commit comments

Comments
 (0)