Skip to content

命令式弹框

以 promise 回调方式使用的 <el-dialog> 弹框组件。将打开弹框组件当做是打开一个异步函数,并从中获取到返回值。

设计初衷

尽量避免使用过于复杂的方式调用弹框。尽可能最简单的方式包装组件,满足简单的业务即可。

实现表单业务的返回值

特别是为了满足弹框内表单的业务。比如说弹框负责完成表单数据交互,完成后返回已经新增或修改的数据。页面随即从返回的数据内做其他接口交互,或者是其他行为。

不再让父组件维护弹框组件的显隐状态

避免让父组件手动管理弹框组件的显示和隐藏。这种方式很麻烦,容易新建很多变量。

最小案例

  1. 必须要提供异步onDialogClose 函数。该函数默认返回布尔值,表示控制弹框是否关闭。
  2. 必须要获得弹框实例,使用内部的异步函数控制弹框是否打开,并从中获取到返回值。
最小案例
loading

底部插槽

使用底部插槽提供 rejectresolve 作用域插槽参数,实现弹框的关闭逻辑。你应该在弹框关闭函数 onDialogClose 内实现全部的弹框关闭逻辑,比如常见的表单校验逻辑。

自己封装弹框关闭按钮
loading

设置弹框属性

dialogProps 内设置 <el-dialog> 的属性即可。

设置弹框标题
loading

部分字段不允许填写且不生效

为了防止使用的时候不小心覆盖掉弹框组件的默认行为,有部分字段被屏蔽使用了。被禁用的,默认使用的字段如下:

ts
/**
 * 命令式弹框不允许外部传递的 el-dialog 属性
 * @description
 * - modelValue 不允许外部来管控弹框组件的`显示`和`隐藏`状态
 * - draggable 弹框固定就是可以拖拽的 避免外部组件覆写掉该配置
 * - beforeClose 不允许弹框组件使用该配置 该配置默认被 `onDialogClose` 函数使用
 */
const notUseElDialogProps = <const>["modelValue", "draggable", "beforeClose"];

export default notUseElDialogProps;

表单弹框例子

以下例子演示了如何使用命令式弹框实现简单的表单业务。

详情
loading

二次封装的注意事项

vueuse 的 createTemplatePromise 的渲染逻辑是:必须要先执行内部的创建组件实例函数

如果二次封装时,直接以本组件为根元素的话,会导致父组件永远无法获取到有效的组件实例。

你应该按照以下方式来二次封装本组件。

必须提供有意义的 dom 元素作为根标签
vue
<script lang="ts" setup>
import ComponentsDialogPromise from "components/dialog-promise/index.vue";
import { defineExpose, ref } from "vue";

const props = ref<DialogPromiseProps<{}>>({
	async onDialogClose({ reject, resolve }) {
		resolve({});
		return true;
	},
});
const dialogRef = useTemplateRef("dialog");
function open() {
	dialogRef.value?.open();
}
defineExpose({
	// 对外导出打开弹框函数
	open,
});
</script>

<template>
	<!-- 你必须要提供一个有意义的根dom元素 否则父级无法获得组件实例 -->
	<section class="must-has-dom-root">
		<ComponentsDialogPromise :="props" ref="dialog" />
	</section>
</template>

<style lang="scss" scoped>
.must-has-dom-root {
}
</style>

实现原理

本组件本质上是对 vueusecreateTemplatePromise 工具做二次封装。

贡献者

The avatar of contributor named as ruan-cat ruan-cat

页面历史