二、路由安装

2020-02-02  本文已影响0人  zdxhxh

插件

Vue.js 提供插件机制,即Vue.use(plugin) 安装VueRouter,这个插件会调用 plugin 对象的install 方法。

所以 Vue.use(plugin),plugin必须拥有一个install方法

如果Vue检测到plugin,并且有install 方法, 则会调用 plugin.install.call(vm,Vue)

而在路由安装过程中,他会做以下事情

源码分析

在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
}
上一篇 下一篇

猜你喜欢

热点阅读