Vue.use()源码阅读
用途
Vue.use()通常用于开发自定义plugin使用,比如
- 添加全局混入(vue-router、vuex等官方插件均在install函数中调用Vue.mixin({ beforeCreate: fn })实例化插件);
- 开发第三方组件,例如实现自定义加载中效果,为Vue.prototype上添加公共方法;
源码阅读
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) {
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
if (installedPlugins.indexOf(plugin) > -1) { // 维护installedPlugins 避免多次注册 之前有注册过就直接返回
return this
}
// additional parameters
const args = toArray(arguments, 1)
args.unshift(this) // 第一个参数是Vue 优势:编写第三方插件不用再额外引入import Vue
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args) // install函数的第一个参数是Vue
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
installedPlugins.push(plugin)
return this
}
}
复制代码
源码解析
- Vue.use()接收两种类型的入参,Object类型 or Function类型,object类型会调用install(),所以必须要提供install属性;function类型会直接被当做install调用;并且将Vue作为第一个参数传入,这样做的优势:在编写第三方插件不再额外引入import Vue库,压缩代码体积;
const args = toArray(arguments, 1)
args.unshift(this) // 第一个参数是Vue 优势:编写第三方插件不用再额外引入import Vue
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args) // install函数的第一个参数是Vue
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
复制代码
- 在Vue上维护私有属性_installedPlugins判断是否重复注册同一个插件,有重复注册则返回,否则添加到私有属性_installedPlugins中,installedPlugins.push(plugin);
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
if (installedPlugins.indexOf(plugin) > -1) { // 维护installedPlugins 避免多次注册 之前有注册过就直接返回
return this
}
复制代码
-
官网上强调要在new Vue(options)实例化之前调用,为什么呢?回顾下Vue.use()使用的初衷,当我们在Vue.prototype上添加原型方法或者调用Vue其他全局api例如directive、filter、component、mixin等,实例化Vue后所有组件实例上都会有扩展的方法、指令、或组件,这一切,是如何实现的呢?
Vue.prototype很好理解,全局api【directive、filter、component、mixin】的实现都是在Vue.options上扩展属性,实例化new Vue会调用_init(),_init()的关键是将Vue.options与实例对象vm.options上,源码如下:
// merge options
if (options && options._isComponent) {
initInternalComponent(vm, options)
} else {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
}
复制代码
export function initInternalComponent (vm: Component, options: InternalComponentOptions) {
const opts = vm.$options = Object.create(vm.constructor.options)
... ...
}
复制代码
同时,_init()会进行生命周期钩子初始化,同时调用beforeCreate()与created()钩子,这样,经过在初始化之前调用Vue.use()才可以将属性扩展到实例化vue上
- 在源码的最后return this,可以方便我们链式调用use()方法
最后,在阅读别人代码的过程,思考与积累是我们提升自己的“捷径”
知名不惧,日日自新
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END