一、背景描述
最近项目中遇到了全局挂载Dialog的需求,在这里记录一下,希望可以帮到大家。
二、Dialog组件封装
Dialog组件结构如下:
2.1 Dialog.vue
<template><!-- 删除文件对话框 --><el-dialog:title="dialogTitle"v-model="dialogVisible":width="dialogWidth":before-close="handleBeforeClose"><div>{{ title }}</div><template #footer><div class="dialog-footer"><el-button @click="handleDialogClose">取 消</el-button><el-buttontype="primary":loading="sureBtnLoading"@click="handleDialogSure">确 定</el-button></div></template></el-dialog>
</template>
<script setup>
import {ref,computed
} from 'vue'
import {deleteFile
} from '@/api/file'
import { ElMessage } from 'element-plus';const props = defineProps({fileInfo: {type: Array,default: [],},title: {type: String,default: "",},width: {type: String,default: "550px",},saveClick: {type: Function,default: () => {},},cancelClick: {type: Function,default: () => {},},remove: {type: Function,default: () => {},}
})const dialogVisible = ref(false) // 窗体显示控制
const dialogWidth = computed(() => {return props.width || "550px"
})
const dialogTitle = computed(() => {return props.title || '删除文件'
})const title = computed(() => {return '此操作将永久删除, 是否继续?'
})const sureBtnLoading = ref(false)
// 关闭回调触发事件
const handleBeforeClose = (done) => {done()
}
// 取消按钮点击事件
const handleDialogClose = () => {props.cancelClick()props.remove()
}
// 确定按钮点击事件
const handleDialogSure = () => {sureBtnLoading.value = truedeleteFile({id: props.fileInfo.id}).then((res) => {sureBtnLoading.value = falseElMessage.success(res.data || '删除成功')props.saveClick()props.remove()}).catch(() => {sureBtnLoading.value = false})
}
</script>
2.2 index.js
import DeleteFileDialog from './Dialog.vue'
import { createApp } from 'vue'let mountNode
let createMount = (opts) => {if(mountNode){ // 确保只存在一个弹框document.body.removeChild(mountNode)mountNode = null}mountNode = document.createElement('div')document.body.appendChild(mountNode)const app = createApp(DeleteFileDialog, {...opts,modelValue: true,remove() { // 传入remove函数,组件内可移除dom 组件内通过props接收app.unmount(mountNode)document.body.removeChild(mountNode)mountNode = null}})return app.mount(mountNode)
}
function DeleteFile(options = {}) {options.id = options.id || 'deleteFile_' + 1 //唯一id 删除组件时用于定位let $init = createMount(options)return $init
}
DeleteFile.install = app => {app.component('delete-file-dialog', DeleteFileDialog)app.config.globalProperties.$deleteFileDialog = DeleteFile
}
export default DeleteFile
三、全局挂载Dialog组件
在main.js中进行全局挂载
import DeleteFileDialog from '@/components/dialog/deleteFile/index.js'
app.use(DeleteFileDialog)
四、使用Dialog组件
proxy.$deleteFileDialog({fileInfo: fileInfo,saveClick: () => {console.log('saveClick---')},cancelClick: () => {console.log('cancelClick---')}
})