背景
一般基于Element-plus的弹窗是声明式子,的需要写在template里面,不太方便,本次咱们直接实现一个指令式调用的弹窗函数
使用示例
js
<script lang="ts" setup>
import { ref } from 'vue';
import { ElButton } from 'element-plus';
import { createModalApi } from './tool';
const counter = ref(0);
const openModal = () => {
/** 创建并显示弹窗 */
const { close, updateProps } = createModalApi(
ElButton, // 弹窗组件
{
// 组件透传参数
type: 'default',
onClick: () => {
close();
},
},
{
default: () => `关闭:${counter.value}`,
},
);
// 模拟更新弹窗参数
setTimeout(() => {
updateProps({
modelValue: false,
});
}, 3000);
};
const start = () => {
setInterval(() => {
counter.value++;
}, 1000);
};
</script>
<template>
<ElButton class="mb-4" type="primary" @click="openModal"> 打开弹窗 </ElButton>
<ElButton class="mb-4" type="primary" @click="start">
点击计数器: {{ counter }}
</ElButton>
</template>
<style lang="scss" scoped></style>
函数代码参考
jsx
import type { App, Component, Slot } from 'vue';
import { createApp, h, reactive } from 'vue';
import { ElDialog } from 'element-plus';
type InternalSlots = Record<string, Slot>;
/** 创建一个弹窗挂载点 */
const createMountRoot = () => {
const el = document.createElement('span');
const randomStr = `${Math.random()}`;
el.setAttribute('id', randomStr);
el.style.position = 'fixed';
el.style.overflow = 'hidden';
return el;
};
export const createModal = (
component: Component,
props: Record<string, any> = {},
slots: InternalSlots = {},
) => {
/** 弹窗实例 */
let modalInstance = null;
/** 弹窗容器vue实例 */
let vueInstance: App<Element> | null = null;
// 使用 reactive 包裹 props,使其具备响应性
const modalProps = reactive({ modelValue: true });
const onClose = () => {
mountRoot?.remove();
vueInstance?.unmount();
};
modalInstance = h(
ElDialog,
{
lockScroll: false,
...modalProps,
onClose: () => {
onClose();
},
},
[
h(
component,
{
...props,
},
{
...slots,
},
),
],
);
const mountRoot = createMountRoot();
document.body.append(mountRoot);
vueInstance = createApp({
render: () => modalInstance,
});
vueInstance.mount(mountRoot);
return {
close: onClose,
updateProps: (newProps: Record<string, any>) => {
if (!modalInstance.component) {
return;
}
Object.assign(modalInstance.component.props, newProps);
},
};
};
有帮助记得一键三连 thanks !