本文次要讲下如何批改 ElementUI 的 Dialog 和 MessageBox 的默认属性。次要包含以下几个方面:
- Dialog 和 MessageBox 简介;
- 批改单次调用的默认属性;
- 全局批改默认属性:
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.alert
,window.confirm
和window.prompt
,这些都是办法。所以,可能是为了和原生 API 保持一致的应用形式,所以把 MessageBox 做成了对应的办法:MessageBox.alert,MessageBox.confirm 和 MessageBox.prompt。此外,还有一个根底的 MessageBox 办法也能够调用。这四个办法也挂载到了 Vue 原型上,别离是 $alert,$confirm,$prompt 和 $msgbox:
原生 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 通过传参的形式批改:
// $alert, $confirm, $prompt 办法与上面相似
this.$msgbox({
...
closeOnClickModal: false
})
全局批改默认属性
在这里,首先说下我解决这个问题的思路:
- 间接搜寻,大部分问题都能搜到解决方案;
- 搜不到或者他人的办法不实用时,查看源码。
我有一个习惯,如果开发工夫还算拮据的话,即便搜到了现成的解决方案,我还是会对照源码摸索下为什么这个计划是可行的。上面的解决方案都对照源码验证过,所以就间接对照源码讲解决方案以及对应源码的地位。
本文波及到的源码以 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 承受两个参数: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
能够实现咱们的目标。当然,该办法也并不是非常完满的,问题如下:
- 未在官网文档中发现该 API 的介绍,这种非官方 API重大依赖 以后应用的版本,官网应该在后续迭代中不保障这种 API 的稳定性和正确性;
-
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,简略点,你能够笼罩这个默认办法或者摸索更适宜你的解决方案。
总结
心愿大家能有所播种。如有谬误,欢送留言探讨。
参考文档
- ElementUI 如何全局配置组件默认属性;
- 全局批改 elementUI 的 $message 默认显示工夫的办法。