前言
最近在看 vue-router 和 vuex 的源码,都会有自己的 install 方法,然后通过 mixin 绑定到生命周期里
vue.use
vue.use 兼容带 install 和不带 install,这两种注册的方式都可以,只是 install 会更容易扩展
export function initUse (Vue: GlobalAPI) {Vue.use = function (plugin: Function | Object) {
<!-- 已经 use 的插件数组 -->
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
if (installedPlugins.indexOf(plugin) > -1) {return this}
// additional parameters
<!-- 把传入的参数整理成数组 -->
const args = toArray(arguments, 1)
<!-- 默认第一个参数是 vue 对象 -->
args.unshift(this)
<!-- 判断带不带 install 方法 -->
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-router
export function install (Vue) {if (install.installed && _Vue === Vue) return // 避免重复加载
install.installed = true // 加载标志
_Vue = Vue
const isDef = v => v !== undefined
const registerInstance = (vm, callVal) => {
let i = vm.$options._parentVnode
if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {i(vm, callVal)
}
}
<!-- 通过 mixin 添加生命周期 -->
Vue.mixin({beforeCreate () {if (isDef(this.$options.router)) {
this._routerRoot = this
this._router = this.$options.router
this._router.init(this)
Vue.util.defineReactive(this, '_route', this._router.history.current)
} else {this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
registerInstance(this, this)
},
destroyed () {registerInstance(this)
}
})
<!-- 所有实例中 this.$router 等同于访问 this._routerRoot._router -->
Object.defineProperty(Vue.prototype, '$router', {get () {return this._routerRoot._router}
})
<!-- 所有实例中 this.$route 等同于访问 this._routerRoot._route -->
Object.defineProperty(Vue.prototype, '$route', {get () {return this._routerRoot._route}
})
Vue.component('RouterView', View)
Vue.component('RouterLink', Link)
const strats = Vue.config.optionMergeStrategies
// use the same hook merging strategy for route hooks
strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}
总结
要写一个 vue 的插件,可以是带 install 或不带,然后在里面通过 mixin,绑定 prototype,调用 component 等方法去注册到 vue 实例上去