mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-06 09:08:51 +08:00
feat: ✨ 优化Toast、Message和Notify组件的函数式调用方案 (#696)
解决当前页面存在多次使用useXX时仅最后一次生效的问题
This commit is contained in:
parent
deeb45d8cb
commit
9f318bdeb3
@ -1,22 +1,19 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2022-12-14 17:33:21
|
||||
* @LastEditTime: 2024-08-17 18:18:16
|
||||
* @LastEditTime: 2024-11-05 23:15:31
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-message-box/index.ts
|
||||
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-message-box\index.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import { provide, ref } from 'vue'
|
||||
import { inject, provide, ref } from 'vue'
|
||||
import type { Message, MessageOptions, MessageResult, MessageType } from './types'
|
||||
import { deepMerge } from '../common/util'
|
||||
|
||||
/**
|
||||
* useMessage 用到的key
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const messageDefaultOptionKey = '__MESSAGE_OPTION__'
|
||||
const messageDefaultOptionKey = '__MESSAGE_OPTION__'
|
||||
|
||||
const None = Symbol('None')
|
||||
|
||||
// 默认模板
|
||||
export const defaultOptions: MessageOptions = {
|
||||
@ -36,9 +33,12 @@ export const defaultOptions: MessageOptions = {
|
||||
}
|
||||
|
||||
export function useMessage(selector: string = ''): Message {
|
||||
const messageOption = ref<MessageOptions>(defaultOptions) // Message选项
|
||||
const messageOptionKey = selector ? messageDefaultOptionKey + selector : messageDefaultOptionKey
|
||||
provide(messageOptionKey, messageOption)
|
||||
const messageOption = inject(messageOptionKey, ref<MessageOptions | typeof None>(None)) // Message选项
|
||||
if (messageOption.value === None) {
|
||||
messageOption.value = defaultOptions
|
||||
provide(messageOptionKey, messageOption)
|
||||
}
|
||||
|
||||
const createMethod = (type: MessageType) => {
|
||||
// 优先级:options->MessageOptions->defaultOptions
|
||||
@ -77,7 +77,9 @@ export function useMessage(selector: string = ''): Message {
|
||||
const prompt = createMethod('prompt')
|
||||
|
||||
const close = () => {
|
||||
messageOption.value.show = false
|
||||
if (messageOption.value !== None) {
|
||||
messageOption.value.show = false
|
||||
}
|
||||
}
|
||||
return {
|
||||
show,
|
||||
@ -87,3 +89,7 @@ export function useMessage(selector: string = ''): Message {
|
||||
close
|
||||
}
|
||||
}
|
||||
|
||||
export const getMessageDefaultOptionKey = (selector: string) => {
|
||||
return selector ? `${messageDefaultOptionKey}${selector}` : messageDefaultOptionKey
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-04-08 22:34:01
|
||||
* @LastEditTime: 2024-09-23 15:59:04
|
||||
* @LastEditTime: 2024-11-05 23:17:06
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-message-box\types.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import { baseProps } from '../common/props'
|
||||
import { baseProps, makeStringProp } from '../common/props'
|
||||
import { type InputType } from '../wd-input/types'
|
||||
|
||||
export type MessageType = 'alert' | 'confirm' | 'prompt'
|
||||
@ -113,5 +113,8 @@ export interface Message {
|
||||
|
||||
export const messageBoxProps = {
|
||||
...baseProps,
|
||||
selector: String
|
||||
/**
|
||||
* 指定唯一标识
|
||||
*/
|
||||
selector: makeStringProp('')
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ import {
|
||||
type MessageResult,
|
||||
type MessageType
|
||||
} from './types'
|
||||
import { defaultOptions, messageDefaultOptionKey } from '.'
|
||||
import { defaultOptions, getMessageDefaultOptionKey } from '.'
|
||||
import { isDef, isFunction } from '../common/util'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { type InputType } from '../wd-input/types'
|
||||
@ -78,7 +78,7 @@ const bodyClass = computed(() => {
|
||||
return `wd-message-box__body ${!title.value ? 'is-no-title' : ''} ${type.value === 'prompt' ? 'is-prompt' : ''}`
|
||||
})
|
||||
|
||||
const messageOptionKey = props.selector ? messageDefaultOptionKey + props.selector : messageDefaultOptionKey
|
||||
const messageOptionKey = getMessageDefaultOptionKey(props.selector)
|
||||
const messageOption = inject(messageOptionKey, ref<MessageOptions>(defaultOptions)) // message选项
|
||||
|
||||
/**
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { provide, reactive } from 'vue'
|
||||
import { inject, provide, reactive, ref } from 'vue'
|
||||
import type { NotifyProps } from './types'
|
||||
import { deepMerge, isString } from '../common/util'
|
||||
|
||||
let timer: ReturnType<typeof setTimeout>
|
||||
let currentOptions = getDefaultOptions()
|
||||
const notifyDefaultOptionKey = '__NOTIFY_OPTION__'
|
||||
const None = Symbol('None')
|
||||
export const setNotifyDefaultOptions = (options: NotifyProps) => {
|
||||
currentOptions = deepMerge(currentOptions, options) as NotifyProps
|
||||
}
|
||||
@ -12,24 +13,28 @@ export const resetNotifyDefaultOptions = () => {
|
||||
currentOptions = getDefaultOptions()
|
||||
}
|
||||
export const useNotify = (selector: string = '') => {
|
||||
const notifyOption = reactive<NotifyProps>(currentOptions)
|
||||
const notifyOptionKey = getNotifyOptionKey(selector)
|
||||
|
||||
const notifyOption = inject(notifyOptionKey, ref<NotifyProps | typeof None>(None))
|
||||
if (notifyOption.value === None) {
|
||||
notifyOption.value = currentOptions
|
||||
provide(notifyOptionKey, notifyOption)
|
||||
}
|
||||
const showNotify = (option: NotifyProps | string) => {
|
||||
const options = deepMerge(currentOptions, isString(option) ? { message: option } : option) as NotifyProps
|
||||
|
||||
Object.assign(notifyOption, options, { visible: true })
|
||||
if (notifyOption.duration && notifyOption.duration > 0) {
|
||||
notifyOption.value = deepMerge(options, { visible: true })
|
||||
if (notifyOption.value.duration && notifyOption.value.duration > 0) {
|
||||
timer && clearTimeout(timer)
|
||||
timer = setTimeout(() => closeNotify(), options.duration)
|
||||
}
|
||||
}
|
||||
const closeNotify = () => {
|
||||
timer && clearTimeout(timer)
|
||||
notifyOption.visible = false
|
||||
if (notifyOption.value !== None) {
|
||||
notifyOption.value.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
// provide
|
||||
provide(getNotifyOptionKey(selector), notifyOption)
|
||||
|
||||
return {
|
||||
showNotify,
|
||||
closeNotify
|
||||
|
||||
@ -16,16 +16,18 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
// #ifdef H5
|
||||
name: 'wd-notify',
|
||||
// #endif
|
||||
options: { virtualHost: true, addGlobalClass: true, styleIsolation: 'shared' }
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import wdPopup from '../wd-popup/wd-popup.vue'
|
||||
import { inject, computed, watch } from 'vue'
|
||||
import { inject, computed, watch, ref } from 'vue'
|
||||
import { notifyProps, type NotifyProps } from './types'
|
||||
import { getNotifyOptionKey } from '.'
|
||||
import { addUnit, isFunction } from '../common/util'
|
||||
@ -37,10 +39,10 @@ const emits = defineEmits<{
|
||||
(e: 'closed'): void
|
||||
(e: 'opened'): void
|
||||
}>()
|
||||
const state = inject<NotifyProps>(getNotifyOptionKey(props.selector), props)
|
||||
const state = inject(getNotifyOptionKey(props.selector), ref<NotifyProps>(props))
|
||||
|
||||
const customStyle = computed(() => {
|
||||
const { safeHeight, position } = state
|
||||
const { safeHeight, position } = state.value
|
||||
let customStyle: string = ''
|
||||
switch (position) {
|
||||
case 'top':
|
||||
@ -56,21 +58,24 @@ const customStyle = computed(() => {
|
||||
})
|
||||
|
||||
const onClick = (event: MouseEvent) => {
|
||||
if (isFunction(state.onClick)) return state.onClick(event)
|
||||
if (isFunction(state.value.onClick)) return state.value.onClick(event)
|
||||
emits('click', event)
|
||||
}
|
||||
const onClosed = () => {
|
||||
if (isFunction(state.onClosed)) return state.onClosed()
|
||||
if (isFunction(state.value.onClosed)) return state.value.onClosed()
|
||||
emits('closed')
|
||||
}
|
||||
const onOpened = () => {
|
||||
if (isFunction(state.onOpened)) return state.onOpened()
|
||||
if (isFunction(state.value.onOpened)) return state.value.onOpened()
|
||||
emits('opened')
|
||||
}
|
||||
|
||||
watch(
|
||||
() => state.visible,
|
||||
(visible) => emits('update:visible', visible as boolean)
|
||||
() => state.value.visible,
|
||||
(visible) => {
|
||||
emits('update:visible', visible as boolean)
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,22 +1,11 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-03-29 13:29:57
|
||||
* @LastEditTime: 2024-07-18 23:16:16
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-toast/index.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import { provide, ref } from 'vue'
|
||||
import { inject, provide, ref } from 'vue'
|
||||
import type { Toast, ToastOptions } from './types'
|
||||
import { deepMerge } from '../common/util'
|
||||
|
||||
/**
|
||||
* useToast 用到的key
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const toastDefaultOptionKey = '__TOAST_OPTION__'
|
||||
const toastDefaultOptionKey = '__TOAST_OPTION__'
|
||||
|
||||
// 默认模板
|
||||
export const defaultOptions: ToastOptions = {
|
||||
@ -30,11 +19,16 @@ export const defaultOptions: ToastOptions = {
|
||||
zIndex: 100
|
||||
}
|
||||
|
||||
const None = Symbol('None')
|
||||
|
||||
export function useToast(selector: string = ''): Toast {
|
||||
const toastOptionKey = getToastOptionKey(selector)
|
||||
const toastOption = inject(toastOptionKey, ref<ToastOptions | typeof None>(None)) // toast选项
|
||||
if (toastOption.value === None) {
|
||||
toastOption.value = defaultOptions
|
||||
provide(toastOptionKey, toastOption)
|
||||
}
|
||||
let timer: ReturnType<typeof setTimeout> | null = null
|
||||
const toastOption = ref<ToastOptions>(defaultOptions) // Toast选项
|
||||
const toastOptionKey = selector ? toastDefaultOptionKey + selector : toastDefaultOptionKey
|
||||
provide(toastOptionKey, toastOption)
|
||||
|
||||
const createMethod = (toastOptions: ToastOptions) => {
|
||||
// 优先级:options->toastOptions->defaultOptions
|
||||
@ -85,6 +79,10 @@ export function useToast(selector: string = ''): Toast {
|
||||
}
|
||||
}
|
||||
|
||||
export const getToastOptionKey = (selector: string) => {
|
||||
return selector ? `${toastDefaultOptionKey}${selector}` : toastDefaultOptionKey
|
||||
}
|
||||
|
||||
export const toastIcon = {
|
||||
success() {
|
||||
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>'
|
||||
|
||||
@ -38,12 +38,11 @@ import wdTransition from '../wd-transition/wd-transition.vue'
|
||||
|
||||
import { computed, inject, onBeforeMount, ref, watch, type CSSProperties } from 'vue'
|
||||
import base64 from '../common/base64'
|
||||
import { defaultOptions, toastDefaultOptionKey, toastIcon } from '.'
|
||||
import { defaultOptions, getToastOptionKey, toastIcon } from '.'
|
||||
import { toastProps, type ToastLoadingType, type ToastOptions } from './types'
|
||||
import { addUnit, isDef, isFunction, objToStyle } from '../common/util'
|
||||
|
||||
const props = defineProps(toastProps)
|
||||
|
||||
const iconName = ref<string>('') // 图标类型
|
||||
const msg = ref<string>('') // 消息内容
|
||||
const position = ref<string>('middle')
|
||||
@ -62,7 +61,7 @@ let opened: (() => void) | null = null
|
||||
|
||||
let closed: (() => void) | null = null
|
||||
|
||||
const toastOptionKey = props.selector ? toastDefaultOptionKey + props.selector : toastDefaultOptionKey
|
||||
const toastOptionKey = getToastOptionKey(props.selector)
|
||||
const toastOption = inject(toastOptionKey, ref<ToastOptions>(defaultOptions)) // toast选项
|
||||
|
||||
// 监听options变化展示
|
||||
|
||||
@ -8,23 +8,15 @@
|
||||
* 记得注释
|
||||
*/
|
||||
|
||||
// Toast
|
||||
export { useToast } from './components/wd-toast'
|
||||
// Messageb
|
||||
export { useMessage } from './components/wd-message-box'
|
||||
|
||||
// useQueue
|
||||
export { useQueue } from './components/composables/useQueue'
|
||||
|
||||
// Notify
|
||||
export * from './components/wd-notify'
|
||||
|
||||
export { dayjs } from './components/common/dayjs'
|
||||
|
||||
export * as CommonUtil from './components/common/util'
|
||||
|
||||
export * as clickOut from './components/common/clickoutside'
|
||||
|
||||
export * from './locale'
|
||||
|
||||
export type { ConfigProviderThemeVars } from './components/wd-config-provider/types'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user