背景

在项目中使用对话框的通常做法是把对话框封装成组件,在使用的地方引入,然后添加到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. 全面了解 Javascript Prototype Chain 原型链

    原型链可以说是Javascript的核心特征之一,当然也是难点之一.学过其它面向对象的编程语言后再学习Javascript多少会感到有些迷惑.虽然Javascript也可以说是面向对象的语言,但是其实 ...

  2. HDU 7066 - NJU emulator(构造题)

    题面传送门 提供一种不同于官方题解.需要的操作次数比官方题解多(官方题解大概是 \(2\times 16\),我这大概是 \(3\times 16\)),但能通过此题的做法. 首先我们考虑一个暴力,我 ...

  3. Codeforces Round #701 (Div. 2) 题解

    由于今天实在是太自闭了就前来写场已经 AK 的 div.2 的题解了 这场比赛是我的 div.2 首 AK 哦 A 先特判 \(b=1\),强制将 \(b+1\) 否则容易发现答案最大为 \(\log ...

  4. 洛谷 P5406 - [THUPC2019]找树(FWT+矩阵树定理)

    题面传送门 首先看到这道题你必须要有一个很清楚的认识:这题新定义的 \(\oplus\) 符号非常奇怪,也没有什么性质而言,因此无法通过解决最优化问题的思路来解决这个问题,只好按照计数题的思路来解决, ...

  5. Assemblytics鉴定基因组间SV

    Assemblytics, 发表在Bioinformaticshttp://www.ncbi.nlm.nih.gov/pubmed/27318204,鉴定基因组间SV. Githup,https:// ...

  6. [linux] 大批量删除任务

    一不小心投了巨多任务,或者投递的资源不合理时,想批量杀掉这些任务. kill的方法就不说了,我这里用qdel的方法. 用了这么一条命令: qstat |sed '1,2d' |awk -F' ' '{ ...

  7. 简易kmeans-c++版本

    typedef double dtype; 主要接口: void Kmeans(const vector<vector<dtype> > &d,int k,string ...

  8. Mac下source tree 下的安装

    安装时出现了以下错误,解决方法 git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=source ...

  9. VSCode+Maven+Hadoop开发环境搭建

    在Maven插件的帮助下,VSCode写Java其实非常方便.这一讲我们介绍如何借助maven用VScode搭建Hadoop开发环境. 1.Java环境安装 首先我们需要搭建好Java开发环境.我们需 ...

  10. 使用微信开放标签<wx-open-launch-weapp>的踩坑日记

    最近在完成H5跳转小程序需求时,使用到了微信官方退出的开放标签<wx-open-launch-weapp>,来谈一谈使用的心得和不足. 1.适用环境微信版本要求为:7.0.12及以上. 系 ...