import { inject, provide, ref } from 'vue' import type { Toast, ToastOptions } from './types' import { deepMerge } from '../common/util' /** * useToast 用到的key */ const toastDefaultOptionKey = '__TOAST_OPTION__' // 默认模板 export const defaultOptions: ToastOptions = { duration: 2000, show: false } const None = Symbol('None') export function useToast(selector: string = ''): Toast { const toastOptionKey = getToastOptionKey(selector) const toastOption = inject(toastOptionKey, ref(None)) // toast选项 if (toastOption.value === None) { toastOption.value = defaultOptions provide(toastOptionKey, toastOption) } let timer: ReturnType | null = null const createMethod = (toastOptions: ToastOptions) => { return (options: ToastOptions | string) => { return show(deepMerge(toastOptions, typeof options === 'string' ? { msg: options } : options) as ToastOptions) } } const show = (option: ToastOptions | string) => { const options = deepMerge(defaultOptions, typeof option === 'string' ? { msg: option } : option) as ToastOptions toastOption.value = deepMerge(options, { show: true }) as ToastOptions // 开始渲染,并在 duration ms之后执行清除 timer && clearTimeout(timer) if (toastOption.value.duration && toastOption.value.duration > 0) { timer = setTimeout(() => { timer && clearTimeout(timer) close() }, options.duration) } } const loading = createMethod({ iconName: 'loading', duration: 0, cover: true }) const success = createMethod({ iconName: 'success', duration: 1500 }) const error = createMethod({ iconName: 'error' }) const warning = createMethod({ iconName: 'warning' }) const info = createMethod({ iconName: 'info' }) const close = () => { toastOption.value = { show: false } } return { show, loading, success, error, warning, info, close } } export const getToastOptionKey = (selector: string) => { return selector ? `${toastDefaultOptionKey}${selector}` : toastDefaultOptionKey } export const toastIcon = { success() { return '' }, warning() { return '' }, info() { return '' }, error() { return '' } }