Vue2 中 ElementUI 中 $message 组件是如何实现的


问题

面试官:在 Vue2 项目中全局配置 ElmentUI 便可在 Vue 局部组件调用 this.$message(options)方法内部是如何实现的?

😂 一时没回答上来,其实之前看过很多 ElementUI 源码的,可能太紧张了。

/* main.js */

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});

那么 ElementUI是如何实现的呢?

分析源码

1.找到 ElementUI 仓库,按下键盘 . 打开 vscode.dev。

2.从 package.json 找到源码 入口文件

  "scripts": {
	// ...
	"build:utils": "cross-env BABEL_ENV=utils babel src --out-dir lib --ignore src/index.js",
	// ...
  },

3. 打开src/index.js, 查看 Message 组件代码

import Message from '../packages/message-box/index.js';

const install = function(Vue, opts = {}) {
  Vue.prototype.$message = Message;
};

/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue);
}

export default {
	install,
	Message,
}
  • Message: 消息提示组件。
  • install 变量: 用于注册 Vue 全局插件时,调用的 install 方法,第一个参数为 Vue 构造函数,第二参数为选项对象 。
  • Vue.prototype.$message: 用于添加 Vue 实例方法。
  • export default {install,Message}: 用于导出一个对象,在 main.js 中可以全局注册组件,添加实例方法。
  1. Message 组件构成
  • message/index.js: 导出一个 Message 组件
  • message/src/main.vue: 定义一个 Message组件
  • message/src/main.js: 通过Vue.extend包装一个Vue 子类 Message
import Vue from "vue";

import Main from "./main.vue";

let instance;

let MessageConstructor = Vue.extend(Main);

const Message = function (options = {}) {
  if (typeof options === "string") {
    options = {
      message: options,
    };
  }

  console.log(instance.$el); // 此时是undefined。
  instance = new MessageConstructor({
    data: options,
  });
  instance.$mount(); // 调用$mount挂载实例后才可获得$el元素。
  console.log(instance.$el); // 此时挂载后才有真实dom(<div class="el-message el-message--success"  >)。
  document.body.appendChild(instance.$el); // 将元素添加到body元素中。

};

export default Message;

代码简单实现

https://github.com/FredBrock/vue2-el-message

总结

  1. 通过 Vue.prototype 原型对象挂载 $message 方法,后续子组件便可全局调用 this.$message
  2. 通过Vue.extend(options) 将基于Message组件来创建Vue组件子类,从而创建新的组件,实现组件的继承和扩展。