写点什么

5 分钟搞定 vue3 函数式弹窗

  • 2024-01-11
    福建
  • 本文字数:2876 字

    阅读完需:约 9 分钟

前言


最近接到一个需求,需要在一些敏感操作进行前要求输入账号和密码,然后将输入的账号和密码加到接口请求的header里面。如果每个页面都去手动导入弹窗组件,在点击按钮后弹出弹窗。再拿到弹窗返回的账号密码后去请求接口也太累了,那么有没有更简单的实现方式呢?



函数式弹窗的使用场景


首先我们来看看什么是函数式弹窗?


函数式弹窗是一种使用函数来创建弹窗的技术。它可以简化弹窗的使用,只需要在需要弹窗的地方调用函数就可以了。那么这里使用函数式弹窗就能完美的解决我们的问题。


我们只需要封装一个showPasswordDialog函数,调用该函数后会弹出一个弹窗。该函数会返回一个resolve后的值就是账号密码的Promise。然后在http请求拦截器中加一个needValidatePassword字段,拦截请求时如果该字段为true,就await调用showPasswordDialog函数。拿到账号和密码后塞到请求的 header 里面。这样就我们就只需要在发起请求的地方加一个needValidatePassword: true配置就行了。



先来实现一个弹窗组件


这个是简化后template中的代码,和 Element Plus 官网中的 demo 代码差不多,没有什么说的。


<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;}
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>
复制代码


再基于弹窗组件实现函数式弹窗


createApp函数和app.mount方法


createApp函数会创建和返回一个vue应用实例,也就是我们平时常说的app,该函数接受两个参数。第一个参数为接收一个组件,也就是我们平时写的vue文件。第二个参数为可选的对象,这个对象会传递给第一个参数组件的props


举个例子:


import MyComponent from "./MyComponent"
const app = createApp(MyComponent, { visible: true})
复制代码


在这个例子中我们基于MyComponent组件生成了一个app应用实例,如果MyComponent组件的props中有定义visible,那么visible就会被赋值为true


调用createApp函数创建的这个应用实例app实际就是在内存中创建的一个对象,并没有渲染到浏览器的 dom 上面。这个时候我们就要调用应用实例app暴露出来的mount方法将这个组件挂载到真实的 dom 上面去。mount方法接收一个“容器”参数,用于将组件挂载上去,可以是一个实际的 DOM 元素或是一个 CSS 选择器字符串。比如下面这个例子是将组件挂载到body上面:


app.mount(document.body)
复制代码


app提供了很多方法和属性,详见 vue官网


封装一个showPasswordDialog函数


首先我们来看看期望如何使用showPasswordDialog函数?


我们希望showPasswordDialog函数返回一个Promiseresolve的值就是弹窗中输入的表单。例如,我们可以使用以下代码使用showPasswordDialog函数:


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属性、closeconfirm回调方法,分别会赋值给弹窗组件 props 中的visiblecloseconfirm

弹窗组件中触发关闭事件时会调用props.close?.(),实际这里就是在调用我们传入的close回调方法。在这个方法中我们调用了实例的unmount方法卸载组件,然后将创建的弹窗组件 dom 从 body 中移除,并且返回一个rejectPromise


当我们将账号和密码输入完成后,会调用props.confirm?.(ruleForm),这里的ruleForm就是我们表单中的账号和密码。实际这里就是在调用我们传入的confirm回调方法,接下来同样也是卸载组件和移除弹窗组件生成的 dom,并且返回一个resolve值为账号密码表单的Promise


总结


这篇文章主要介绍了如何创建函数式弹窗:


  1. 创建一个常规的弹窗组件,有点不同的是closeconfirm事件不是定义在emits中,而是作为回调定义在props中。


  1. 创建一个showPasswordDialog函数,该函数返回一个Promiseresolve的值就是我们弹窗中输入的表单。


  1. 调用createApp函数将步骤一的弹窗组件作为第一个参数传入,并且第二个对象参数中传入属性visibletrue打开弹窗和注入弹窗close关闭和confirm确认的回调。


  1. 使用者只需await调用showPasswordDialog就可以打开弹窗和拿到表单中填入的账号和密码。


文章转载自:欧阳码农

原文链接:https://www.cnblogs.com/heavenYJJ/p/17955954

体验地址:http://www.jnpfsoft.com/?from=001

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
5分钟搞定vue3函数式弹窗_Java_不在线第一只蜗牛_InfoQ写作社区