You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
vite-vue3-lowcode/src/visual-editor/hooks/useModal.tsx

111 lines
2.5 KiB

/**
* @name: useModal
* @author: 卜启缘
* @date: 2021/5/7 15:26
* @description:useModal
* @update: 2021/5/7 15:26
*/
import {
defineComponent,
reactive,
createApp,
PropType,
getCurrentInstance,
ComponentInternalInstance,
isVNode
} from 'vue'
import { ElButton, ElDialog } from 'element-plus'
import { isFunction } from '@/visual-editor/utils/is'
interface ModalOptions {
title?: string
footer?: null | (() => JSX.Element)
content: ComponentInternalInstance | (() => JSX.Element)
onConfirm?: () => void
onCancel?: () => void
props?: {
[propName: string]: any
}
}
const Modal = defineComponent({
props: {
options: {
type: Object as PropType<ModalOptions>,
default: () => ({})
}
},
setup(props) {
const instance = getCurrentInstance()!
const state = reactive({
options: props.options,
visible: true
})
const methods = {
service: (options: ModalOptions) => {
state.options = options
methods.show()
},
show: () => (state.visible = true),
hide: () => (state.visible = false)
}
const handler = {
onConfirm: async () => {
await state.options.onConfirm?.()
methods.hide()
},
onCancel: () => {
state.options.onCancel?.()
methods.hide()
}
}
Object.assign(instance.proxy, methods)
return () => (
<ElDialog
modelValue={state.visible}
title={state.options.title}
destroyOnClose={true}
{...state.options.props}
onClose={handler.onCancel}
>
{{
default: () =>
isVNode(state.options.content) ? (
<content />
) : isFunction(state.options.content) ? (
state.options.content()
) : null,
footer: () =>
state.options.footer === null ? null : (
<div>
<ElButton {...({ onClick: handler.onCancel } as any)}></ElButton>
<ElButton type={'primary'} {...({ onClick: handler.onConfirm } as any)}>
</ElButton>
</div>
)
}}
</ElDialog>
)
}
})
export const useModal = (() => {
let instance: any
return (options: ModalOptions) => {
if (instance) {
instance.service(options)
return instance
}
const div = document.createElement('div')
document.body.appendChild(div)
const app = createApp(Modal, { options })
instance = app.mount(div)
return instance
}
})()