element-ui MessageBox组件源码分析整理笔记(十二)

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 };

你可能感兴趣的:(element-ui MessageBox组件源码分析整理笔记(十二))