<template> <el-dialog :model-value="visible" title="账号和密码" @close="handleClose"> <!-- 省略账号、密码表单部分... --> <el-button type="primary" @click="submitForm()">提交</el-button> </el-dialog> </template>这个是简化后的script代码,大部分和Element Plus官网的demo代码差不多。需要注意的是我们这里将close关闭事件和confirm确认事件定义在了props中,而不是在emits中,因为后面函数式组件会通过props将这两个回调传入进来。具体的我们下面会讲。
<script setup lang="ts"> interface Props { visible: boolean; close?: () => void; confirm?: (data) => void; } // 堆代码 duidaima.com const props = defineProps<Props>(); const emit = defineEmits(["update:visible"]); const submitForm = async () => { // 省略validate表单校验的代码 // 这里的data为表单中输入的账号密码 props.confirm?.(data); handleClose(); }; const handleClose = () => { emit("update:visible", false); props.close?.(); }; </script>再基于弹窗组件实现函数式弹窗
import MyComponent from "./MyComponent" const app = createApp(MyComponent, { visible: true })在这个例子中我们基于MyComponent组件生成了一个app应用实例,如果MyComponent组件的props中有定义visible,那么visible就会被赋值为true。
app.mount(document.body)app提供了很多方法和属性,详见 vue官网。
try { // 调用这个就会弹出弹窗 const res: RuleForm = await showPasswordDialog(); // 这个res就是输入的账号密码 console.log("res", res); } catch (error) { console.log(error); }具体如何实现showPasswordDialog函数?
经过上面的介绍我们知道了可以调用createApp函数传入指定组件生成app,然后使用app.mount方法将这个组件挂载到指定的dom上面去。那么现在思路就清晰了,我们只需要将我们前面实现的弹窗组件作为第一个参数传递给createApp函数。第二个参数传入一个对象给弹窗组件的props,用以控制打开弹窗和注册弹窗关闭和确认的事件回调。
下面是实现的showPasswordDialog函数:
import { App, createApp } from "vue"; import PasswordDialog from "./index.vue"; // 这个index.vue就是我们前面实现的弹窗组件 export async function showPasswordDialog(): Promise<RuleForm> { return new Promise((resolve, reject) => { let mountNode = document.createElement("div"); let dialogApp: App<Element> | undefined = createApp(PasswordDialog, { visible: true, close: () => { if (dialogApp) { dialogApp.unmount(); document.body.removeChild(mountNode); dialogApp = undefined; reject("close"); } }, confirm: (res: RuleForm) => { resolve(res); dialogApp?.unmount(); document.body.removeChild(mountNode); dialogApp = undefined; }, }); document.body.appendChild(mountNode); dialogApp.mount(mountNode); }); }在这个showPasswordDialog函数中我们先创建了一个div元素,再将弹窗组件传递给了createApp函数生成一个dialogApp的实例。然后将创建的div元素挂载到body上面,再调用mount方法将我们的弹窗组件挂载到创建的div元素上,至此我们实现了通过函数式调用将弹窗组件渲染到body中。现在我们再来看看传入到createApp函数的第二个对象参数,我们给这个对象分别传入了visible属性、close和confirm回调方法,分别会赋值给弹窗组件props中的visible、close、confirm。