本文次要讲下如何批改ElementUI的Dialog和MessageBox的默认属性。次要包含以下几个方面:

  1. Dialog和MessageBox简介;
  2. 批改单次调用的默认属性;
  3. 全局批改默认属性:
    3.1 Dialog全局批改默认属性;
    3.2 MessageBox全局批改默认属性。

以下例子以批改close-on-click-modal属性为例进行解说。这个属性的默认值是true,也就是点击蒙层的时候弹框敞开。在理论我的项目中,咱们个别不想要这个默认行为,所以拿这个属性举例。

Dialog和MessageBox简介

Dialog是一个组件Component
MessageBox这个名字尽管咋一看也像是组件名,然而却是一个办法名
我试着猜想了下MessageBox没有做成组件的起因。依据官网的介绍:

A set of modal boxes simulating system message box, mainly for alerting information, confirm operations and prompting messages.

MessageBox次要是为了模拟零碎原生的弹框,而零碎原生弹框的API是window.alertwindow.confirmwindow.prompt,这些都是办法。所以,可能是为了和原生API保持一致的应用形式,所以把MessageBox做成了对应的办法:MessageBox.alert,MessageBox.confirm和MessageBox.prompt。此外,还有一个根底的MessageBox办法也能够调用。这四个办法也挂载到了Vue原型上,别离是$alert,$confirm,$prompt和$msgbox:

原生APIMessageBox办法名Vue实例办法名
-MessageBox$msgbox
window.alertMessageBox.alert$alert
window.confirmMessageBox.confirm$confirm
window.promptMessageBox.prompt$prompt

正因为Dialog和MessageBox实质是不一样的,所以批改默认属性的形式也就不一样了,上面会针对这两种类型别离进行阐明。

批改单次调用的默认属性

批改单次调用的默认属性就比较简单了,Dialog组件通过属性的形式批改:close-on-click-modal

<el-dialog  ...  :close-on-click-modal="false">  ...</el-dialog>

MessageBox通过传参的形式批改:

// $alert, $confirm, $prompt办法与上面相似this.$msgbox({  ...  closeOnClickModal: false})

全局批改默认属性

在这里,首先说下我解决这个问题的思路:

  1. 间接搜寻,大部分问题都能搜到解决方案;
  2. 搜不到或者他人的办法不实用时,查看源码。

我有一个习惯,如果开发工夫还算拮据的话,即便搜到了现成的解决方案,我还是会对照源码摸索下为什么这个计划是可行的。上面的解决方案都对照源码验证过,所以就间接对照源码讲解决方案以及对应源码的地位。

本文波及到的源码以v2.15.1版本为例。

Dialog全局批改默认属性

Dialog组件源码位于/packages/dialog文件夹上面github地址。
查看/packages/dialog/component.vue文件会发现closeOnClickModal是一个props:

props: {  // ...  closeOnClickModal: {    type: Boolean,    default: true // 默认值是true  },  // ...}

全局批改形式如下:

import Element from 'element-ui'Element.Dialog.props.closeOnClickModal.default = false

MessageBox全局批改默认属性

首先看下/src/index.js文件中和MessageBox相干的代码:

// ...import MessageBox from '../packages/message-box/index.js';// ...const install = function(Vue, opts = {}) {  // ...  Vue.prototype.$msgbox = MessageBox; // 对应于下面表格中的对应关系:MessageBox => $msgbox  Vue.prototype.$alert = MessageBox.alert; // 对应于下面表格中的对应关系:MessageBox.alert => $alert  Vue.prototype.$confirm = MessageBox.confirm; // 对应于下面表格中的对应关系:Message.confirm => $confirm  Vue.prototype.$prompt = MessageBox.prompt; // 对应于下面表格中的对应关系:MessageBox.prompt => $prompt  // ...}export default {  // ...  MessageBox,  // ...}

接下来看下MessageBox的定义文件/packages/message-box/src/main.js,MessageBox承受两个参数:optionscallback,字面含意应该就是配置对象和回调函数:

const MessageBox = function(options, callback) {  // ...};

我应用了$msgbox,所以我的第一思路是批改$msgbox办法,调用MessageBox的时候增加自定义参数:

import Element from 'element-ui' import Vue from 'vue'Vue.prototype.$msgbox = function (options, ...args) {  options = Object.assign({    closeOnClickModal: false  }, options)  Element.MessageBox(options, ...args)}

测试了下,没有问题,然而认真看了下源码,发现options并不一定是对象,也能够是字符串:

const MessageBox = function(options, callback) {  if (Vue.prototype.$isServer) return;  if (typeof options === 'string' || isVNode(options)) { // 第一个参数是字符串的时候,当作message    options = {      message: options    };    if (typeof arguments[1] === 'string') { // 第二个参数是字符串的时候,当作title      options.title = arguments[1];    }  } else if (options.callback && !callback) {    callback = options.callback;  }  // ...}

我测试没有问题,是因为我调用的时候options都是当对象应用的。所以这个计划是有限定范畴的解决方案,并不是通用的。次要有以下问题:

  1. options必须是对象的模式;
  2. 如果应用了$alert$confirm$prompt等办法,都须要做相似的解决,代码比拟啰嗦;
  3. 只能通过$msgbox的形式批改,如果你是间接调用的MessageBox,那就不实用了,因为我并没有批改MessageBox

基于问题1,你能够像MessageBox源码外面剖析参数那样,创立一个适合的options,而后传给MessageBox。基于问题3,临时没有想到好的解决方案。

思考到我的项目是团队单干的后果,万一有同学调用$msgbox的时候第一个参数不是对象,或者间接通过MessageBox调用,我就在思考是否有更好的解决方案。认真查看源码,发现一个更简略的API:

MessageBox.setDefaults = defaults => {  MessageBox.defaults = defaults;};

再从新看下MessageBox函数的源码:

const MessageBox = function(options, callback) {  // ...  if (typeof Promise !== 'undefined') {    return new Promise((resolve, reject) => { // eslint-disable-line      msgQueue.push({        options: merge({}, defaults, MessageBox.defaults, options), // 留神这一行        callback: callback,        resolve: resolve,        reject: reject      });      showNextMsg();    });  } else {    msgQueue.push({      options: merge({}, defaults, MessageBox.defaults, options), // 留神这一行      callback: callback    });    showNextMsg();  }};

通过下面最终options参数的计算方法,咱们能够给options排下优先级:

函数调用时传入的options > MessageBox.defaults > 组件默认值options

所以,批改MessageBox.defaults能够实现咱们的目标。当然,该办法也并不是非常完满的,问题如下:

  1. 未在官网文档中发现该API的介绍,这种非官方API重大依赖以后应用的版本,官网应该在后续迭代中不保障这种API的稳定性和正确性;
  2. MessageBox.alert在调用Message的时候,默认笼罩了几个默认属性,这几个属性通过MessageBox.setDefaults办法批改不失效,比方设置alert框的closeOnClickModal为true:

    MessageBox.alert = (message, title, options) => {  // ...  return MessageBox(merge({    // ...    closeOnPressEscape: false,    closeOnClickModal: false // 调用MessageBox时传入的options会笼罩MessageBox.defaults  }, options));};

摸索到这里,对于我来说,MessageBox.setDefaults曾经算是比拟优的解决方案了,所以就不再持续摸索了。
如果你还有更高的要求,比方修复问题2,简略点,你能够笼罩这个默认办法或者摸索更适宜你的解决方案。

总结

心愿大家能有所播种。如有谬误,欢送留言探讨。

参考文档

  1. ElementUI 如何全局配置组件默认属性;
  2. 全局批改elementUI的$message默认显示工夫的办法。