解决在全局使用同一类弹框如登录弹框,在认证过期后需要重新弹出弹框
使用hooks
import { createVNode, render, getCurrentInstance } from "vue";
const getAppendToElement = (props) => {
let appendTo = document.body;
if (props.appendTo) {
if (typeof props.appendTo === "string") {
appendTo = document.querySelector(props.appendTo);
}
if (props.appendTo instanceof HTMLElement) {
appendTo = props.appendTo;
}
if (!(appendTo instanceof HTMLElement)) {
appendTo = document.body;
}
}
return appendTo;
};
const initInstance = (Component, props, container, appContext = null) => {
const vNode = createVNode(Component, props);
vNode.appContext = appContext;
render(vNode, container);
getAppendToElement(props).appendChild(container);
return vNode;
};
export const useCommandComponent = (Component) => {
var _a, _b;
const appContext = (_a = getCurrentInstance()) === null || _a === void 0 ? void 0 : _a.appContext;
if (appContext) {
const currentProvides = (_b = getCurrentInstance()) === null || _b === void 0 ? void 0 : _b.provides;
Reflect.set(appContext, "provides", Object.assign(Object.assign({}, appContext.provides), currentProvides));
}
const container = document.createElement("div");
const close = () => {
var _a;
render(null, container);
(_a = container.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(container);
};
const CommandComponent = (options) => {
var _a;
if (!Reflect.has(options, "visible")) {
options.visible = true;
}
if (typeof options.onClose !== "function") {
options.onClose = close;
}
else {
const originOnclose = options.onClose;
options.onClose = () => {
originOnclose();
close();
};
}
const vNode = initInstance(Component, options, container, appContext);
const vm = (_a = vNode.component) === null || _a === void 0 ? void 0 : _a.proxy;
for (const prop in options) {
if (Reflect.has(options, prop) && !Reflect.has(vm.$props, prop)) {
vm[prop] = options[prop];
}
}
return vNode;
};
CommandComponent.close = close;
return CommandComponent;
};
export default useCommandComponent;
简单的dialog
<script setup lang="ts">
import { computed } from "vue";
import { ElDialog } from "element-plus";
const props = defineProps<{
visible: boolean;
title?: string;
}>();
const emits = defineEmits<{
(event: "update:visible", visible: boolean): void;
(event: "close"): void;
}>();
const visible = computed<boolean>({
get() {
return props.visible;
},
set(visible) {
emits("update:visible", visible);
if (!visible) {
emits("close");
}
}
});
</script>
<template>
<ElDialog v-model="visible" :title="title" width="30%">
<span>This is a message</span>
<template #footer>
<span>
<el-button @click="visible = false">Cancel</el-button>
<el-button type="primary" @click="visible = false"> Confirm </el-button>
</span>
</template>
</ElDialog>
</template>
使用
const myDialog = useCommandComponent(MyDialog);
const handleDialog = () => {
myDialog({
title: "父组件弹窗",
dialogVisible: true,
onSubmit: () => myDialog.close(),
onCancel: () => myDialog.close()
});
};