本文主要讲下如何修改ElementUI的Dialog和MessageBox的默认属性。主要包括如下几个方面:vue
如下例子以修改close-on-click-modal
属性为例进行讲解。这个属性的默认值是true
,也就是点击蒙层的时候弹框关闭。在实际项目中,咱们通常不想要这个默认行为,因此拿这个属性举例。git
Dialog是一个组件Component。
MessageBox这个名字虽然咋一看也像是组件名,可是倒是一个方法名。
我试着猜想了下MessageBox没有作成组件的缘由。根据官网的介绍:github
A set of modal boxes simulating system message box, mainly for alerting information, confirm operations and prompting messages.
MessageBox主要是为了模仿系统原生的弹框,而系统原生弹框的API是window.alert
,window.confirm
和window.prompt
,这些都是方法。因此,多是为了和原生API保持一致的使用方式,因此把MessageBox作成了对应的方法:MessageBox.alert,MessageBox.confirm和MessageBox.prompt。此外,还有一个基础的MessageBox方法也能够调用。这四个方法也挂载到了Vue原型上,分别是$alert,$confirm,$prompt和$msgbox:element-ui
原生API | MessageBox方法名 | Vue实例方法名 |
---|---|---|
- | MessageBox | $msgbox |
window.alert | MessageBox.alert | $alert |
window.confirm | MessageBox.confirm | $confirm |
window.prompt | MessageBox.prompt | $prompt |
正由于Dialog和MessageBox本质是不同的,因此修改默认属性的方式也就不同了,下面会针对这两种类型分别进行说明。函数
修改单次调用的默认属性就比较简单了,Dialog组件经过属性的方式修改:close-on-click-modal测试
<el-dialog ... :close-on-click-modal="false"> ... </el-dialog>
MessageBox经过传参的方式修改:ui
// $alert, $confirm, $prompt方法与下面相似 this.$msgbox({ ... closeOnClickModal: false })
在这里,首先说下我解决这个问题的思路:this
我有一个习惯,若是开发时间还算宽裕的话,即便搜到了现成的解决方案,我仍是会对照源码探索下为何这个方案是可行的。下面的解决方案都对照源码验证过,因此就直接对照源码讲解决方案以及对应源码的位置。.net
本文涉及到的源码以v2.15.1版本为例。prototype
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
首先看下/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接受两个参数:options
和callback
,字面含义应该就是配置对象和回调函数:
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
都是当对象使用的。因此这个方案是有限定范围的解决方案,并非通用的。主要有如下问题:
options
必须是对象的形式;$alert
,$confirm
,$prompt
等方法,都须要作相似的处理,代码比较啰嗦;$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
能够实现咱们的目的:
import Element from 'element-ui' Element.MessageBox.setDefaults({ closeOnClickModal: false })
固然,该方法也并非十分完美的,问题以下:
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,简单点,你能够覆盖这个默认方法或者探索更适合你的解决方案。
但愿你们能有所收获。若有错误,欢迎留言讨论。