本文主要講下如何修改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,簡單點,你能夠覆蓋這個默認方法或者探索更適合你的解決方案。
但願你們能有所收穫。若有錯誤,歡迎留言討論。