介绍
在vue3中,有很多开发环境中都需要使用弹框,传统的element-plus需要控制变量来显示隐藏,如果单文件中有多个弹窗就需要维护多个变量,这样维护起来不方便,这时候就可以考虑使用命令式弹窗方案,不足点就是表单组件需要单独创建。
一、基本实现
弹窗组件
import { createApp, h, ref } from 'vue';
import { ElDialog, ElButton } from 'element-plus';
/**
* @param component 弹窗默认内容-插槽名为#default
* @param props 弹窗默认内容的属性
* @param modalProps 弹窗属性
*/
export function renderDialog(component, props, modalProps) {
const open = ref(true);
const loading = ref(false);
const instance = ref();
//dialog必须是函数式组件
const dialog = () =>
h(
ElDialog,
{
...modalProps,
modelValue: open.value,
onClosed() {
app.unmount();
document.body.removeChild(div);
},
},
{
default: () => h(component, { ...props, ref: instance }),
footer: () =>
h('div', { className: 'dialog-footer' }, [
h(ElButton, { onClick: cancel }, () => '取 消'),
h(
ElButton,
{ type: 'primary', onClick: submit, loading: loading.value },
() => '确 认'
),
]),
}
);
const app = createApp(dialog);
const div = document.createElement('div');
document.body.appendChild(div);
app.mount(div);
//确认按钮
async function submit() {
loading.value = true;
try {
await instance.value?.submit?.();
open.value = false;
} finally {
loading.value = false;
}
}
//取消按钮
function cancel() {
open.value = false;
}
}
表单组件
根据自身需求创建对应的表单组件
<script setup lang="ts">
import { reactive, ref } from 'vue';
const form = reactive({ name: '' });
const formRef = ref();
const rules = reactive({
name: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
});
defineExpose({
async submit() {
await formRef.value.validate();
return new Promise((resolve) => {
setTimeout(() => {
console.log('提交成功');
resolve('提交成功');
}, 1500);
});
},
});
</script>
<template>
<el-form :model="form" ref="formRef" label-width="auto" style="max-width: 600px" :rules="rules">
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" />
</el-form-item>
</el-form>
</template>
<style scoped></style>
使用方法
import { renderDialog } from './utils/index.ts';
renderDialog(Form, {}, { title: '登录' });
总结
该方案主要是为了不在单文件中重复维护多个变量,声明式弹窗和命令式弹窗各有优势,欢迎交流补充!