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 中可以全局注册组件,添加实例方法。
- 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
总结
- 通过 Vue.prototype 原型对象挂载
$message
方法,后续子组件便可全局调用this.$message
。 - 通过Vue.extend(options) 将基于Message组件来创建Vue组件子类,从而创建新的组件,实现组件的继承和扩展。