背景

在项目中使用对话框的通常做法是把对话框封装成组件,在使用的地方引入,然后添加到template,使用visible.sync控制对话框的显示/隐藏,监听confirm事件处理用户点击确定。如下:

1 <confirm-dialog
2 v-if="confirmDialogVisible"
3 :title="$t(`mineData.tips.deleteDataset`)"
4 :visible.sync="confirmDialogVisible"
5 @confirm="confimHandler"
6 ></confirm-dialog>

在封装的dialog内部也需要在关闭时更新visible,确定时触发confirm事件:

1 methods: {
2 close() {
3 this.$emit("update:visible", false);
4 },
5 confirm() {
6 this.close();
7 this.$emit("confirm");
8 }
9 }

这样的做法不仅仅导致页面初始化时引入所有对话框组件而影响加载速度,更头疼的是页面中引入了很多对话框时,会导致页面很杂乱:需要为每个对话框插入一段html,为每个对话框维护一个单独的visible变量,为每个对话框添加confirm事件监听...

而这些操作大部分是和业务无关的,且这些操作又是极其相似的。

那么,有没有通过js动态创建dialog的方法呢?

1 createDialog("confirm-dialog.vue");

就像上面这样根据文件名即可打开对话框,不用定义visible及添加一堆html和事件回调,甚至不需要先引入对话框组件!

是不是很简单!心动了吧?看下去吧。

实现

1.封装的/utils/dialogControl.js

 1 import Vue from 'vue'
2 async function createDialog (fileName, data) {
3 const dialogsContext = require.context(
4 '../components', // 定义查找文件的范围
5 true,
6 /([a-zA-Z\-0-9]+)\.vue$/, // 定义文件名规则
7 'lazy'
8 )
9 // 查找到传入名字的文件并加载该文件
10 let match = dialogsContext.keys().find((key) => key.includes(fileName))
11 if (!match) return
12 let componentContext = await dialogsContext(match)
13 let temp = componentContext.default
14 return new Promise(function (resolve, reject) {
15 // 初始化配置参数
16 let opt = {
17 data
18 }
19 let component = Object.assign({}, temp)
20 let initData = {
21 visible: true
22 }
23 Object.assign(initData, component.data())
24 opt.data && Object.assign(initData, JSON.parse(JSON.stringify(opt.data)))
25 component.data = function () {
26 return initData
27 }
28 // 创建构造器创建实例挂载
29 let DialogC = Vue.extend(component)
30 let dialog = new DialogC()
31 // 关闭事件
32 let _onClose = dialog.$options.methods.onClose
33 dialog.onClose = function () {
34 resolve()
35 dialog.$destroy()
36 _onClose && _onClose.call(dialog)
37 document.body.removeChild(dialog.$el)
38 }
39 // 回调事件
40 let _onCallback = dialog.$options.methods.onCallback
41 dialog.onCallback = function (...arg) {
42 try {
43 _onCallback && _onCallback()
44 resolve(arg)
45 dialog.$destroy()
46 _onClose && _onClose.call(dialog)
47 document.body.removeChild(dialog.$el)
48 } catch (e) {
49 console.log(e)
50 }
51 }
52 dialog.$mount()
53 // 点击关闭按钮时会改变visible
54 dialog.$watch('visible', function (n, o) {
55 dialog === false && dialog.onClose()
56 })
57 document.body.appendChild(dialog.$el)
58 })
59 }
60
61 export { createDialog }

说明:

1.需要指定查找文件的路径及匹配名称的正则表达式,这样能过滤掉一些不需要的文件

2.接收一个fileName参数用于匹配要打开的对话框文件,data参数是传递给对话框的数据,会合并到组件的data中

3.使用visible变量控制对话框的显示/隐藏

4.定义了一个onClose方法用于关闭对话框,对话框中可以使用该方法进行关闭

5.onCallback方法用于向调用对话框的父组件传值,如点击确定按钮时向父组件传值

2.dialog文件定义

如/components/ConfirmDialog.vue,使用visible变量控制显示/隐藏,onClose处理关闭事件,确定按钮的回调是onCallback(和dialogControl.js中的定义一致)。

 1 <template>
2 <el-dialog title="提示" :visible.sync="visible" width="30%">
3 <span>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Nesciunt quis
4 perspiciatis fugiat molestiae provident accusantium repudiandae fugit
5 minima, eaque, repellat quibusdam iste sed ad? Debitis qui praesentium
6 minus incidunt esse!</span>
7 <span slot="footer" class="dialog-footer">
8 <el-button @click="onClose">取 消</el-button>
9 <el-button type="primary" @click="onCallback(true)">确 定</el-button>
10 </span>
11 </el-dialog>
12 </template>
13
14 <script>
15 export default {
16 data () {
17 return {}
18 },
19 methods: {
20 }}
21 </script>

3.使用

引入dialogControl中的createDialog方法,直接传入文件名称即可打开。

如果有其他的属性,则以键值对的形式放入第二个参数,这些属性会合并到对话框组件的data中,因此对话框组件中可以直接使用这些属性。

createDialog方法得到一个promise对象,其then方法能得到confirm返回的结果。

 1 <template>
2 <div>
3 <h1>This is an show page</h1>
4 <el-button type="primary" @click="openDialog">打开</el-button>
5 </div>
6 </template>
7
8 <script>
9 import { createDialog } from "@/utils/dialogControl";
10 export default {
11 methods: {
12 openDialog() {
13 let dialog = createDialog("confirm-dialog.vue");
14 dialog.then((v) => {
15 if (v) {
16 console.info("确定");
17 }
18 });
19 },
20 },
21 };
22 </script>

效果如下:

如果你还在使用文章开始的方式调用对话框,那么赶紧把这个方法用起来吧!

参考:

https://www.freesion.com/article/43311065748/

vue+el-element中根据文件名动态创建dialog的方法的更多相关文章

  1. odoo 动态创建字段的方法

    动态创建字段并非一个常见的的需求,但某些情况下,我们确实又需要动态地创建字段. Odoo 中创建字段的方法有两种,一种是通过python文件class中进行定义,另一种是在界面上手工创建,odoo通过 ...

  2. Visual c++例子,可不使用常规的对话框资源模板的情况下,动态创建对话框的方法

    详细说明:Visual c++例子,可不使用常规的对话框资源模板的情况下,动态创建对话框的方法.该方法可以在运行时在内存中直接建立对话框资源,使用起来更为灵活.适用于多个开发项目共享有界面的公用程序模 ...

  3. python-获取类名和方法名,动态创建类和方法及属性

    获取类名和方法名1.在函数外部获取函数名称,用.__name__获取2.在函数内部获取当前函数名称,用sys._getframe().f_code.co_name方法获取3.使用inspect模块动态 ...

  4. .Net 中的反射(动态创建类型实例) - Part.4

    动态创建对象 在前面节中,我们先了解了反射,然后利用反射查看了类型信息,并学习了如何创建自定义特性,并利用反射来遍历它.可以说,前面三节,我们学习的都是反射是什么,在接下来的章节中,我们将学习反射可以 ...

  5. .Net 中的反射(动态创建类型实例)

    动态创建对象 在前面节中,我们先了解了反射,然后利用反射查看了类型信息,并学习了如何创建自定义特性,并利用反射来遍历它.可以说,前面三节,我们学习的都是反射是什么,在接下来的章节中,我们将学习反射可以 ...

  6. js中几种动态创建元素并设置文本内容的比较,及性能测试。

    内容 1 appendChild (都兼容) 2.insertAdjacentHTML (都兼容) 3.innerHTML (都兼容) 4.createDocumentFragment (都兼容) 动 ...

  7. 程序员:java中直接或间接创建线程的方法总结

    在java开发中,经常会涉及多线程的编码,那么通过直接或间接创建线程的方法有哪些?现整理如下: 1.继承Thread类,重写run()方法 class Worker extends Thread { ...

  8. 在TFS中通过程序动态创建Bug并感知Bug解决状态

    为便于跟踪问题解决情况,预警引擎产生的比较严重的预警日志,需要在TFS中登记Bug,通过TFS的状态流转,利用TFS Bug的Web挂钩功能,动态感知Bug解决状态,从而跟踪预警问题的解决状态, 整体 ...

  9. [UE4]C++中SpawnActor用法(动态创建Actor)

    转自:http://aigo.iteye.com/blog/2270177 C++中创建一个Level并添加的Runtime当中 C++中Spawn一个基于蓝图的Actor https://answe ...

随机推荐

  1. Codeforces 251D - Two Sets(异或方程组)

    题面传送门 题意: 你有一个可重集 \(S=\{a_1,a_2,\dots,a_n\}\),你要把它划分成两个可重集 \(S_1,S_2\) 使得 \(S\) 中每个元素都恰好属于 \(S_1\) 与 ...

  2. 洛谷 P7451 - [THUSCH2017] 杜老师(线性基+根分+结论题)

    题面传送门 看到乘积为平方数我们可以很自然地想到这道题,具体来说,我们对 \(1\sim 10^7\) 中所有质因子标号 \(1,2,\cdots,\pi(10^7)\),对于 \(x\in[l,r] ...

  3. GORM基本使用

    GORM 目录 GORM 1. 安装 2. 数据库连接 3. 数据库迁移及表操作 1. 安装 go get -u github.com/jinzhu/gorm 要连接数据库首先要导入驱动程序 // G ...

  4. rabbit mq的一个实例,异步功能

    简单的使用场景:消息队列的场景有:解耦,异步,削峰. 此例用的场景,异步 有时候会有请求消耗时间过长,不能老让用户等待返回结果,可以用消息队列来做异步实现,之前用过workmain等类似的异步,但不如 ...

  5. du命令之计算文件大小

    在linux中,常用du命令来计算文件或目录的大小 名称: du - 计算每个文件的磁盘用量,目录则取总用量. 用法: du [选项]... [文件]... 常用选项 -a, --all 输出所有文件 ...

  6. 学习java 7.18

    学习内容: Lambda表达式的格式:(形式参数)  ->  {代码块} 如果有多个参数,参数之间用逗号隔开 new Thread(  ()   ->   { System.out.pri ...

  7. accommodate ~ ache

    accommodate The accommodation reflex [反射] (or accommodation-convergence [会聚] reflex) is a reflex act ...

  8. 大数据学习day21-----spark04------1. 广播变量 2. RDD中的cache 3.RDD的checkpoint方法 4. 计算学科最受欢迎老师TopN

    1. 广播变量  1.1 补充知识(来源:https://blog.csdn.net/huashetianzu/article/details/7821674) 之所以存在reduce side jo ...

  9. Linux基础命令---mysqldump数据库备份

    mysqldump mysqldump是一个客户端的备份程序,他可以备份数据库,或者将数据库传输到另外一个服务器. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora. ...

  10. Linux基础命令---put上传ftp文件

    put 使用lftp登录ftp服务器之后,可以使用put指令将文件上传到服务器.   1.语法       put [-E]  [-a]  [-c] [-O base]  lfile  [-o rfi ...