MessageBox组件源码,有添加部分注释
main.vue
main.js
const defaults = {
title: null, //MessageBox 标题
message: '', //MessageBox 消息正文内容
type: '', //消息类型,用于显示图标
iconClass: '', //自定义图标的类名,会覆盖 type
showInput: false, //是否显示输入框
showClose: true, //MessageBox 是否显示右上角关闭按钮
modalFade: true,
lockScroll: true,//是否在 MessageBox 出现时将 body 滚动锁定
closeOnClickModal: true, //是否可通过点击遮罩关闭 MessageBox
closeOnPressEscape: true, //是否可通过按下 ESC 键关闭 MessageBox
closeOnHashChange: true, //是否在 hashchange 时关闭 MessageBox
inputValue: null, //输入框的初始文本
inputPlaceholder: '', //输入框的占位符
inputType: 'text', //输入框的类型
inputPattern: null, //输入框的校验表达式
inputValidator: null, //输入框的校验函数。可以返回布尔值或字符串,若返回一个字符串, 则返回结果会被赋值给 inputErrorMessage
inputErrorMessage: '', //校验未通过时的提示文本
showConfirmButton: true, //是否显示确定按钮
showCancelButton: false, //是否显示取消按钮
confirmButtonPosition: 'right', //
confirmButtonHighlight: false,
cancelButtonHighlight: false,
confirmButtonText: '', //确定按钮的文本内容
cancelButtonText: '', //取消按钮的文本内容
confirmButtonClass: '', //确定按钮的自定义类名
cancelButtonClass: '', //取消按钮的自定义类名
customClass: '', //MessageBox 的自定义类名
beforeClose: null, //MessageBox 关闭前的回调,会暂停实例的关闭
dangerouslyUseHTMLString: false, //是否将取消(点击取消按钮)与关闭(点击关闭按钮或遮罩层、按下 ESC 键)进行区分
center: false, //是否居中布局
roundButton: false, //是否使用圆角按钮
distinguishCancelAndClose: false //是否将取消(点击取消按钮)与关闭(点击关闭按钮或遮罩层、按下 ESC 键)进行区分
};
import Vue from 'vue';
import msgboxVue from './main.vue';
import merge from 'element-ui/src/utils/merge';
import { isVNode } from 'element-ui/src/utils/vdom';
//创建MessageBox的构造器,包含msgboxVue组件选项的对象作为Vue.extend的参数,返回一个VueComponent类,VueComponent类是Vue类的子类
//Vue.extend是一个类构造器,用来创建一个子类vue并返回构造函数,而Vue.component它的任务是将给定的构造函数与字符串ID相关联,以便Vue.js可以在模板中接收它。
const MessageBoxConstructor = Vue.extend(msgboxVue);
let currentMsg, instance;
let msgQueue = [];
const defaultCallback = action => {
if (currentMsg) {
let callback = currentMsg.callback;
if (typeof callback === 'function') {
if (instance.showInput) {
callback(instance.inputValue, action);
} else {
callback(action);
}
}
if (currentMsg.resolve) {
// 点击确定或者去下关闭按钮时,在此处调对应的方法进行处理
if (action === 'confirm') { //执行确认后的回调方法
if (instance.showInput) {
currentMsg.resolve({ value: instance.inputValue, action });
} else {
currentMsg.resolve(action);
}
} else if (currentMsg.reject && (action === 'cancel' || action === 'close')) { //执行取消和关闭后的回调方法
currentMsg.reject(action);
}
}
}
};
const initInstance = () => {
//instance为messageBox的实例
instance = new MessageBoxConstructor({
el: document.createElement('div')
});
instance.callback = defaultCallback;
};
const showNextMsg = () => {
if (!instance) {
// 调用initInstance初始化实例,返回messageBox的实例对象
initInstance();
}
instance.action = '';
if (!instance.visible || instance.closeTimer) {
if (msgQueue.length > 0) {
currentMsg = msgQueue.shift();
let options = currentMsg.options;
//将用户设置的属性和方法挂载到messageBox的实例对象instance上去
for (let prop in options) {
if (options.hasOwnProperty(prop)) {
instance[prop] = options[prop];
}
}
//当用户未设置callback时,将defaultCallback赋值给instance.callback
if (options.callback === undefined) {
instance.callback = defaultCallback;
}
let oldCb = instance.callback;
instance.callback = (action, instance) => {
oldCb(action, instance);
showNextMsg();
};
if (isVNode(instance.message)) {
instance.$slots.default = [instance.message];
instance.message = null;
} else {
delete instance.$slots.default;
}
['modal', 'showClose', 'closeOnClickModal', 'closeOnPressEscape', 'closeOnHashChange'].forEach(prop => {
if (instance[prop] === undefined) {
instance[prop] = true;
}
});
document.body.appendChild(instance.$el);
Vue.nextTick(() => {
instance.visible = true;
});
}
}
};
const MessageBox = function(options, callback) {
if (Vue.prototype.$isServer) return;
if (typeof options === 'string' || isVNode(options)) {
options = {
message: options
};
if (typeof arguments[1] === 'string') {
options.title = arguments[1];
}
} else if (options.callback && !callback) {
callback = options.callback;
}
if (typeof Promise !== 'undefined') {
return new Promise((resolve, reject) => { // eslint-disable-line
// options合并默认的所有参数和用户设置的参数
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();
}
};
MessageBox.setDefaults = defaults => {
MessageBox.defaults = defaults;
};
//this.$alert方法
MessageBox.alert = (message, title, options) => {
//如果title的类型为object时,用户可能没传title,则将title的值赋值给options
if (typeof title === 'object') {
options = title;
title = '';
} else if (title === undefined) {
title = '';
}
//合并用户传的参数,并调用MessageBox方法
return MessageBox(merge({
title: title,
message: message,
$type: 'alert',
closeOnPressEscape: false,
closeOnClickModal: false
}, options));
};
//this.$confirm方法,分析同MessageBox.alert方法
MessageBox.confirm = (message, title, options) => {
if (typeof title === 'object') {
options = title;
title = '';
} else if (title === undefined) {
title = '';
}
return MessageBox(merge({
title: title,
message: message,
$type: 'confirm',
showCancelButton: true
}, options));
};
//this.$prompt方法,分析同MessageBox.alert方法
MessageBox.prompt = (message, title, options) => {
if (typeof title === 'object') {
options = title;
title = '';
} else if (title === undefined) {
title = '';
}
return MessageBox(merge({
title: title,
message: message,
showCancelButton: true,
showInput: true,
$type: 'prompt'
}, options));
};
MessageBox.close = () => {
instance.doClose();
instance.visible = false;
msgQueue = [];
currentMsg = null;
};
export default MessageBox;
export { MessageBox };