插件
Vue.js 提供插件机制,即Vue.use(plugin)
安装VueRouter,这个插件会调用 plugin 对象的install 方法。
所以 Vue.use(plugin)
,plugin必须拥有一个install方法
如果Vue检测到plugin,并且有install 方法, 则会调用 plugin.install.call(vm,Vue)
而在路由安装过程中,他会做以下事情
- 装饰
beforeCreate
该钩子函数,对this._router.history.current
进行双向绑定,在该值改变的时候触发视图的更新,同时在该钩子触发router.init()
方法 - 定义
$router
与$route
在Vue
原型链上 - 注册了两个视图组件 也就是
route-view
与link
源码分析
在index.js 中
import { install } from './install'
// 赋值 install
VueRouter.install = install
在./install中
import View from './components/view'
import Link from './components/link'
// 导出一个Vue的引用 它不想把Vue打包进插件 而又想使用Vue的某些方法
export let _Vue
export function install (Vue) {
// 如果已经安装了,并且 _Vue有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
// i = vm.$options._parentVnode.data.registerRouteInstance
if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
i(vm, callVal)
}
}
// 使用Vue.mixin 装饰 beforeCreate、destoryed方法
Vue.mixin({
beforeCreate () {
// 根据optiosn.router判断是否为根节点
if (isDef(this.$options.router)) {
// 如果this是根节点
this._routerRoot = this // 私有属性 : 路由根节点
this._router = this.$options.router // 私有属性 router引用
this._router.init(this) // 触发router的init方法
// 这一步很关键,监听_route的改变 会触发视图的更新 第二个参数为默认值
Vue.util.defineReactive(this, '_route', this._router.history.current)
} else {
// 如果this是子节点
// 将 _ routerRoot赋值为 父节点
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
// 通过registerRouteInstance方法注册router实例
registerInstance(this, this)
},
destroyed () {
registerInstance(this)
}
})
// this._routerRoot._router = this._router.history.current
// 使用 this.$router.push / go 实际上就是该对象
Object.defineProperty(Vue.prototype, '$router', {
get () { return this._routerRoot._router }
})
// 定义$route 属性 拿到当前url对应的路由对象
Object.defineProperty(Vue.prototype, '$route', {
get () { return this._routerRoot._route }
})
// 这里注册了两个视图组件 也就是 route-view 与 link
Vue.component('RouterView', View)
Vue.component('RouterLink', Link)
// 该对象保存了两个option合并的规则 TODO
const strats = Vue.config.optionMergeStrategies
// use the same hook merging strategy for route hooks
strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}
网友评论