思路
useDialog函数:
1、创建一个div节点,将它插入到body节点下
2、再创建一个mounted()函数,里面包含一个vnode,当调用mouted函数进行挂载时,通过render函数将该vnode渲染到刚刚创建的div节点下。
3、再创建一个unmount()函数,渲染为null,关闭弹出的时候卸载,这样我们就不需要在每个组件引入dialog并且每个dialog要声明一个变量控制它是否显示了。
引用
useDialog.ts
import { useDialog } from '@/hooks/dialog'
const useDialogs = useDialog()
// 打开账单弹框
useDialogs.mounted({
component: XXX(弹窗插槽组件),
dialogProps: {
title: '标题',
width: '960px'
},
childrenProps: {
note: '一些自定义传值字段',
onRemoves: () => {
useDialogs.unmount()
},
onHandleConfirm: async () => {
loading.value = true
useDialogs.unmount()
}
}
})
hooks函数封装 - 完整代码
dialog.ts
import { ElDialog } from 'element-plus'
import { getCurrentInstance, h, render, VNode } from 'vue'
export function useDialog() {
const div = document.createElement('div')
document.body.appendChild(div)
const current = getCurrentInstance()
function mounted(opt: any) {
const vnode = h(
ElDialog,
{
modelValue: true,
title: '默认弹框',
closOnClickModal: false,
...opt.dialogProps,
customClass: `app-custom_dialog ${opt.dialogProps.customClass || ''}`,
onRemove: () => unmount(),
'onUpdate:modelValue': (v: boolean) => {
if (!v) {
unmount()
}
}
},
{
// ElDialog 默认插槽
default: () =>
h(opt.component, {
...opt.childrenProps,
onRemove: () => {
unmount()
}
}),
...opt.childrenSlot
}
)
vnode.appContext = current?.appContext!
render(vnode, div)
return unmount
}
function unmount() {
render(null, div)
}
return {
mounted,
unmount
}
}