这是我参与8月更文挑战的第22天,活动详情查看: 8月更文挑战
序言
今天我们老大给我么将了一下Vue.use的工作原理,一开始他以为我们都会,没想到一圈下来竟然都不尽如意,原来表面看起来很熟悉的东西,认真总结,却发现遗漏的东西很多,并不连通,今天我们就来整理一下Vue.use的工作原理吧。
基本使用
在探寻工作原理之前,我们先来看下官方是如何定义我们使用的
- 添加全局方法或者 property。如:vue-custom-element
Vue.myGlobalMethod = function () {
// 逻辑...
}
- 添加全局资源:指令/过滤器/过渡等。如 vue-touch
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
- 通过全局混入来添加一些组件选项。如 vue-router
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
- 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
- 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router
Vue中的插件
看完了使用方法,我们看见,我们把要注册的插件引用作为参数传入,就能实现注册,那么我们的插件是如何完成注册的呢。 在这之前,我们看一下符合注册规则的插件长啥样。
- 插件的本质是一个函数或者是对象
- 如果是对象的话,里面要有一个install方法,为什么要Install方法呢,耐心看到执行流程你就会明白。
一个插件的例子
//为对象时
export default{
objectPlugin
}
function install (Vue, option){
console.log(vue);
console.log(option);
Vue.prototype.coolFish = coolFish
}
function coolFish (food){
console.log(`coolFish like ${food}`)
}
//为function时
function funcPlugin(a,b){
console.log('Plugin2 第一个参数:',a)
console.log('Plugin2 第二个参数:',b)
}
我们通过分析上面代码,知道当插件为对象时, 有一个install 方法接受一个 Vue 实例和一个参数option,执行的操作为把当前的方法挂载到原型上面。当插件为function时,一切看起来很正常,我们接下来看一下Vue.use的源码,来理解一下为什么会这么做。
Vue.use源码分析
import { toArray } from '../util/index'
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) {
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters
const args = toArray(arguments, 1)
args.unshift(this)
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
installedPlugins.push(plugin)
return this
}
}
上面这段是Vue.use的源码片段,可以分为一下几个步骤
- 创建一个插件数组,并且检测传入插件是否已经在此数组中,如果有的话,就不注册,直接返回,以免插件重复注册。
- 将 options 类数组对象转换为数组,再将 Vue 实例插入,做第一项。
- 判断当前插件是否有 install 方法,有的话将参数使用apply传入,这样我们前面定义的install 方法就取到了 Vue 实例,完成原型挂载。
- 如果插件本身为一个函数,那么直接把当前参数绑定上去。
- 最后把绑定完成的方法,加入到注册列表,防止重复注册。
总结: 这样就解释了为啥当插件为对象时,需要 install 方法,这样才能把他绑定到原型上,完成动态注册。