Vue3全局挂载Dialog组件

一、背景描述

最近项目中遇到了全局挂载Dialog的需求,在这里记录一下,希望可以帮到大家。

二、Dialog组件封装

Dialog组件结构如下:

2.1 Dialog.vue
javascript 复制代码
<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-button
          type="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 = true
  deleteFile({
    id: props.fileInfo.id
  })
    .then((res) => {
      sureBtnLoading.value = false
      ElMessage.success(res.data || '删除成功')
      props.saveClick()
      props.remove()
    })
    .catch(() => {
      sureBtnLoading.value = false
    })
}
</script>
2.2 index.js
javascript 复制代码
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中进行全局挂载

javascript 复制代码
import DeleteFileDialog from '@/components/dialog/deleteFile/index.js'
app.use(DeleteFileDialog)

四、使用Dialog组件

javascript 复制代码
proxy.$deleteFileDialog({
    fileInfo: fileInfo,
    saveClick: () => {
		console.log('saveClick---')
	},
	cancelClick: () => {
		console.log('cancelClick---')
	}
})

五、效果图

相关推荐
东方小月13 分钟前
从零开发一个 Coding Agent(八):如何使用 Agent 类管理对话状态
前端·人工智能
张元清33 分钟前
React useEventSource Hook:自带断线重连的 Server-Sent Events (2026)
javascript·react.js
光影少年35 分钟前
RN 网络请求:Fetch / Axios 封装、超时、拦截器
前端·react native·react.js
学习星球1 小时前
Vue 3 实战:拆解 RealWorld 项目
前端·vue.js
铁皮饭盒1 小时前
网页端, 6.5MB人脸识别模型, 谷歌框架, 又快又准
前端·javascript·后端
xiaohaiAIgeo1 小时前
【2026年】ASHRAE 110与EN 14175通风柜测试标准对比:进口与国产品牌性能差距
java·前端·数据库·科普知识
自进化Agent智能体1 小时前
Hermes 工具与工具集——Hermes 的内置能力
javascript
用户2930750976691 小时前
TypeScript 必考题:Type 与 Interface 全面对比
前端
hunterandroid2 小时前
[鸿蒙从零到一] HarmonyOS 媒体能力实战:图片、音频与视频处理
前端
打呵欠的猫2 小时前
我让 AI 封装了一个 ImageUpload 组件,它设计的 5 层校验链路比我想的周全
前端·ai编程