- 之前在使用Vue做项目时,经常会用到
Vue.use(plugins[,options])
这种方式去将一个组件绑定到Vue的全局实例上,这样,我们就不需要在每个页面都引入和注册组件便可以直接使用了,例如:Vant组件的挂载:
import Vue from "vue";
import {
Tabbar,
TabbarItem,
Toast,
Icon,
Skeleton,
Swipe,
SwipeItem,
Dialog,
Image,
Lazyload,
NavBar,
ImagePreview,
CellGroup,
Cell,
Field,
Button,
NumberKeyboard,
SwitchCell,
Notify,
Popup,
PullRefresh,
Calendar,
Picker,
List,
Row,
Col,
Loading,
Tag,
Collapse,
CollapseItem,
Tab,
Tabs,
Sticky,
Switch,
Search,
NoticeBar,
Sidebar,
SidebarItem
} from "vant";
Vue.use(Tabbar);
Vue.use(TabbarItem);
Vue.use(Toast);
Vue.use(Icon);
Vue.use(Skeleton);
Vue.use(Swipe);
Vue.use(SwipeItem);
Vue.use(Dialog);
Vue.use(Image);
Vue.use(Lazyload);
Vue.use(NavBar);
Vue.use(ImagePreview);
Vue.use(CellGroup);
Vue.use(Cell);
Vue.use(Field);
Vue.use(Button);
Vue.use(NumberKeyboard);
Vue.use(SwitchCell);
Vue.use(Notify);
Vue.use(Popup);
Vue.use(PullRefresh);
Vue.use(Calendar);
Vue.use(Picker);
Vue.use(List);
Vue.use(Row);
Vue.use(Col);
Vue.use(Loading);
Vue.use(Tag);
Vue.use(Collapse);
Vue.use(CollapseItem);
Vue.use(Tabs);
Vue.use(Tab);
Vue.use(Sticky);
Vue.use(Switch);
Vue.use(Search);
Vue.use(NoticeBar);
Vue.use(Sidebar);
Vue.use(SidebarItem);
最近深入学习了一下Vue的源码,于是便研究了一下Vue的这种组件挂载方式的原理和实现方式,并写了一个简单的实例模拟这个组件挂载过程。具体细节不多讲,请看下面源码,源码中有注释:
Vue.js 本文件旨在模拟Vue,但仅为了演示组件挂载过程,其他代码未实现
const {initUse} = require("./VueUse");
// 模拟Vue构造函数
let Vue = function () {
this.version = '__VERSION__';
};
// 模拟Vue的组件挂载方法,此处仅将所给组件挂载到Vue原型链上,省略其他无关步骤
Vue.component = function(name,component){
Vue.prototype[`$${name}`] = component;
};
// 初始化Vue的use方法,可以通过Vue.use()的方式将组件注册到Vue的全局实例上
initUse(Vue);
module.exports = Vue;
VueUse.js 本文件即为实现Vue.use的主要逻辑代码
const _ = require("../utils");
/**
* 初始化Vue的use方法
* @param Vue 传入Vue对象
*/
module.exports.initUse = function (Vue={}) {
/**
* 在Vue上扩展静态方法use,用于挂载插件到Vue的实例上
* @param plugins 插件对象
* @returns {Vue}
*/
Vue.use = function (plugins) {
// 获取当前Vue实例上的已经安装的插件列表,若要安装的插件已经安装,则直接返回,无需重复安装
const _installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
if(_installedPlugins.indexOf(plugins)>-1){
return this;
}
// 安装插件时可能需要传递一些额外的参数,将除plugins之外的其他参数都转化为数组形式
let args = _.toArray(arguments,1);
// 将当前Vue实例对象作为第一个参数加入参数数组
args.unshift(this);
//如果目标插件存在install方法,则直接调用install方法对插件进行安装
if(plugins.install&&typeof plugins.install === "function"){
plugins.install.apply(plugins,args);
}else if(typeof plugins === "function"){
//若目标插件不存在install方法,并且目标插件是一个函数,则直接调用该函数
plugins.apply(plugins,args);
}
//将当前插件加入到已安装插件列表
_installedPlugins.push(plugins);
return this;
}
};
utils.js 工具类
module.exports = {
toArray: (arrayLike,start=0) => {
if(arrayLike.length===undefined){
return arrayLike;
}
let i = arrayLike.length - start;
let res = new Array(i);
while (i--){
res[i] = arrayLike[i+start]
}
return res;
}
};
plugins1.js 实例组件1
class MyPlugins{
constructor(){
}
showName(name,age){
console.log(`你好,我叫${name},今年${age}岁`);
console.log(`来自:${this.options.from}`);
}
install(Vue,options){
this.options = options;
Vue.component("myPlugins",this);
}
}
module.exports = new MyPlugins();
plugins2.js 实例组件2
class MyPlugins{
constructor(){
}
showName(name,age){
console.log(`hello,my name is ${name},I'm ${age} years old`);
console.log(`from:${this.options.from}`);
}
install(Vue,options){
// 传给插件的参数
this.options = options;
// 将当前组件注册到Vue实例上
Vue.component("myPluginsEn",this);
}
}
module.exports = new MyPlugins();
test.js 用户测试组件挂载结果
const Vue = require("./Vue");
const MyPlugins = require("./plugins1");
const MyPluginsEn = require("./plugins2");
//将目标组件挂载到Vue实力上
Vue.use(MyPlugins,{from: 'china'})
.use(MyPluginsEn,{from: 'U.S'});
let vue = new Vue();
//直接调用目标组件下的方法完成调用
vue.$myPlugins.showName('kiner',20);
vue.$myPluginsEn.showName('kanger',18);
最终输出结果:
到此,组件挂载的简易版本就算完成了。
PS: 本文仅为个人学习Vue源码时的记录,文中若有不妥之处,还请指正,谢谢!