u
This commit is contained in:
1 parent
d37d92996a
commit
a8f3e58a27
25 files changed
+1401
-399
No files matched your search
@@ -0,0 +1,158 @@
|
||||
import type { AppContext, VNode } from 'vue'
|
||||
import { createVNode, getCurrentInstance, nextTick, render } from 'vue'
|
||||
import Modal from './index'
|
||||
|
||||
function omit<T extends Record<string, any>, K extends keyof T>(
|
||||
object: T,
|
||||
keys: K[],
|
||||
): Omit<T, K> {
|
||||
const result = { ...object }
|
||||
keys.forEach(key => delete result[key])
|
||||
return result
|
||||
}
|
||||
|
||||
export interface ModalOptions {
|
||||
layout?: string | VNode | (() => VNode)
|
||||
|
||||
title?: string | VNode | (() => VNode)
|
||||
content?: string | VNode | (() => VNode)
|
||||
footer?: string | VNode | (() => VNode)
|
||||
position?: 'top' | 'center' | 'bottom'
|
||||
confirmBtnProps?: Record<string, any>
|
||||
cancelBtnProps?: Record<string, any>
|
||||
width?: string
|
||||
height?: string
|
||||
fullscreen?: boolean
|
||||
showClose?: boolean
|
||||
showFullscreen?: boolean
|
||||
draggable?: boolean
|
||||
draggableSelector?: string
|
||||
confirmBtn?: any
|
||||
cancelBtn?: any
|
||||
mask?: boolean
|
||||
maskClosable?: boolean
|
||||
onConfirm?: () => void
|
||||
onCancel?: () => void
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
function createModal(options: ModalOptions & { type?: string }, appContext?: AppContext) {
|
||||
let container: HTMLDivElement | null = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
|
||||
let vm: VNode
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (vm.component)
|
||||
vm.component.props.visible = false
|
||||
options.onConfirm?.()
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
if (vm.component)
|
||||
vm.component.props.visible = false
|
||||
options.onCancel?.()
|
||||
}
|
||||
|
||||
const handleClose = async () => {
|
||||
await nextTick()
|
||||
if (container) {
|
||||
render(null, container)
|
||||
document.body.removeChild(container)
|
||||
}
|
||||
container = null
|
||||
options.onClose?.()
|
||||
}
|
||||
|
||||
const defaultConfig = {
|
||||
visible: true,
|
||||
onConfirm: handleConfirm,
|
||||
onCancel: handleCancel,
|
||||
onClose: handleClose,
|
||||
type: options.type ?? 'default',
|
||||
}
|
||||
vm = createVNode(
|
||||
Modal,
|
||||
{
|
||||
...defaultConfig,
|
||||
...omit(options, ['layout', 'content', 'title', 'footer', 'onConfirm', 'onCancel', 'onClose']),
|
||||
},
|
||||
options.layout
|
||||
? {
|
||||
layout:
|
||||
typeof options.layout === 'function'
|
||||
? options.layout
|
||||
: () => options.layout,
|
||||
}
|
||||
: {
|
||||
default: options.content
|
||||
? typeof options.content === 'function'
|
||||
? options.content
|
||||
: () => options.content
|
||||
: undefined,
|
||||
title: options.title
|
||||
? typeof options.title === 'function'
|
||||
? options.title
|
||||
: () => options.title
|
||||
: undefined,
|
||||
footer: options.footer
|
||||
? typeof options.footer === 'function'
|
||||
? options.footer
|
||||
: () => options.footer
|
||||
: undefined,
|
||||
},
|
||||
)
|
||||
|
||||
// 自动获取 appContext,除非手动传入
|
||||
const instanceAppContext = appContext ?? getCurrentInstance()?.appContext ?? undefined
|
||||
if (instanceAppContext) {
|
||||
vm.appContext = instanceAppContext
|
||||
}
|
||||
|
||||
render(vm, container)
|
||||
|
||||
return {
|
||||
close: () => {
|
||||
if (vm.component)
|
||||
vm.component.props.visible = false
|
||||
},
|
||||
update: (newOptions: Partial<ModalOptions>) => {
|
||||
if (vm.component) {
|
||||
Object.entries(newOptions).forEach(([key, val]) => {
|
||||
vm.component!.props[key] = val
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type ModalType = 'default' | 'info' | 'success' | 'warning' | 'danger' | 'question'
|
||||
|
||||
export function useModal() {
|
||||
const open = (options: ModalOptions & { type?: ModalType }, appContext?: AppContext) =>
|
||||
createModal({ ...options, type: options.type ?? 'default' }, appContext)
|
||||
|
||||
const info = (options: ModalOptions, appContext?: AppContext) =>
|
||||
createModal({ ...options, type: 'info' }, appContext)
|
||||
|
||||
const success = (options: ModalOptions, appContext?: AppContext) =>
|
||||
createModal({ ...options, type: 'success' }, appContext)
|
||||
|
||||
const warning = (options: ModalOptions, appContext?: AppContext) =>
|
||||
createModal({ ...options, type: 'warning' }, appContext)
|
||||
|
||||
const danger = (options: ModalOptions, appContext?: AppContext) =>
|
||||
createModal({ ...options, type: 'danger' }, appContext)
|
||||
|
||||
const question = (options: ModalOptions, appContext?: AppContext) =>
|
||||
createModal({ ...options, type: 'question' }, appContext)
|
||||
|
||||
return {
|
||||
open,
|
||||
info,
|
||||
success,
|
||||
warning,
|
||||
danger,
|
||||
question,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user