Vue3封装全局弹窗组件(结合el-dialog)

在main.ts中

import App from "./App.vue";
import SubDialog from '@/components/sub.js'
let instance: any = null;
instance = createApp(App)
instance.use(SubDialog)
instance.mount(document.getElementById("app")}

在components下的sub.js

import SubDialog from './SubDialog.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(SubDialog, {
    ...opts,
     modelValue: true,
    remove() { //传入remove函数,组件内可移除dom 组件内通过props接收
      app.unmount(mountNode)
      document.body.removeChild(mountNode)
    }
  })
  return app.mount(mountNode)
}
function V3Popup(options = {}) {
  options.id = options.id || 'v3popup_' + 1 //唯一id 删除组件时用于定位
  let $inst = createMount(options)
  return $inst
}
V3Popup.install = app => {
  app.component('v3-popup', SubDialog)
  app.config.globalProperties.$subDialog = V3Popup
  // app.provide('subDialog', V3Popup)
}
export default V3Popup

components下的SubDialog.vue

<template>
  <!-- 封装弹框 -->
  <div>
    <el-dialog
      custom-class="subDialog"
      :title="dialogTitle"
      v-model="dialogPopVisible"
      :width="popupWidth"
      :before-close="onBeforeClose"
      :center="true"
    >
      <div>输入内容</div>
      <template #footer class="dialog-footer">
        footer
    </el-dialog>
  </div>
</template>
<script setup lang="ts">
import { ref, computed, defineProps } from "vue";
const props = defineProps({
  title: {
    type: String,
    default: "",
  },
  width: {
    type: String,
    default: "550px",
  },
  option: {
    type: Object,
    default: {
      //可传递其他值
    },
  },
  cancelClick: {
    type: Function,
    default: () => {},
  },
  saveClick: {
    type: Function,
    default: () => {},
  },
});
const dialogPopVisible = ref(true); // 窗体显示控制
const popupWidth = computed(() => {
  return props.width || "550px";
});
const dialogTitle = computed(() => {
  return props.title || "标题";
});
const Cancel = () => {
  dialogPopVisible.value = false;
  props.cancelClick();
};
const Save = () => {
  dialogPopVisible.value = false;
  props.saveClick('传值');
};
const onBeforeClose = (done) => {
  done();
};
</script>

<style lang="scss">
.subDialog {
  &.el-dialog {
    z-index: 99;
    background-color: #ffffff;
    margin-top: 20% !important;
  }
  .el-dialog__header {
    width: 100%;
    height: 50px;
    line-height: 50px;
    box-sizing: border-box;
    padding: 0 25px;
    text-align: left;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  }
  .el-dialog__headerbtn {
    font-size: 20px;
    width: 40px;
    height: 40px;
  }
  .el-dialog__title {
    font-size: 18px;
    font-family: PingFangSC-Medium, PingFang SC;
    font-weight: 500;
    color: rgba(0, 0, 0, 0.85);
  }
  .el-dialog__body {
    box-sizing: border-box;
    padding: 20px 25px;
  }
  .el-dialog__footer {
    text-align: right;
    height: 60px;
    line-height: 60px;
    padding: 0;
    margin-right: 20px;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
  }
}
</style>

.vue中使用

const { proxy }: any = getCurrentInstance();
proxy.$subDialog({
    title: "title",
    width: "550px",
    option: {

    },
    cancelClick: () => {},
    saveClick: async (val) => {
      console.log(val)
    },
  });

你可能感兴趣的:(javascript,vue.js,typescript,vue)