学习vue-router源码记录-1

由于本人开发中使用的是VUE技术栈,最近也是开始源码的学习,以此记录我的理解,若行文有误,请多多指教。vue

1.new Router和install

在vue中咱们使用vue-router时须要先进行new Router(),执行new Router()后主要执行代码看看VueRouter class定义的constructor方法。node

constructor (options: RouterOptions = {}) {
    this.app = null
    this.apps = []
    this.options = options
    this.beforeHooks = []
    this.resolveHooks = []
    this.afterHooks = []
    this.matcher = createMatcher(options.routes || [], this)

    let mode = options.mode || 'hash'
    this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false
    if (this.fallback) {
      mode = 'hash'
    }
    if (!inBrowser) {
      mode = 'abstract'
    }
    this.mode = mode

    switch (mode) {
      case 'history':
        this.history = new HTML5History(this, options.base)
        break
      case 'hash':
        this.history = new HashHistory(this, options.base, this.fallback)
        break
      case 'abstract':
        this.history = new AbstractHistory(this, options.base)
        break
      default:
        if (process.env.NODE_ENV !== 'production') {
          assert(false, `invalid mode: ${mode}`)
        }
    }
  }
复制代码

从代码里面咱们能够看到在new的时候肯定了使用何种路由模式,而且根据传入options建立matchervue-router

接下来看看当使用vue.use()执行install方法作了什么:bash

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)
    }
  }

  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)
    }
  })

  Object.defineProperty(Vue.prototype, '$router', {
    get () { return this._routerRoot._router }
  })

  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
}
复制代码

install方法里主要是Vue.mixin给每一个组件混入了beforeCreatedestroyed 方法,在Vue的原型链上增长了$router$route对象,这就是为何咱们使用Vue的时候在this上能够拿到这两个对象,注册了router-viewrouter-link两个组件。app

2. matcher和route

接下来看看matcher的定义:学习

export type Matcher = {
  match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
  addRoutes: (routes: Array<RouteConfig>) => void;
};
复制代码

matcher暴露了match方法addRoutes方法,从方法的名字上看,match方法是用于路由匹配,addRoutes则是用来添加路由配置。ui

在执行creatMatcher()里第一代段代码生成了pathListpathMapnameMap这三个对象,这是后面路由执行匹配很是重要的配置。this

const { pathList, pathMap, nameMap } = createRouteMap(routes)
复制代码

pathMapnameMap分别是以route配置的path和name为key生成的一个映射表,对应value为RouteRecord实例。spa

下面看看RouteRecord的定义:prototype

declare type RouteRecord = {
  path: string;
  regex: RouteRegExp;
  components: Dictionary<any>;
  instances: Dictionary<any>;
  name: ?string;
  parent: ?RouteRecord;
  redirect: ?RedirectOption;
  matchAs: ?string;
  beforeEnter: ?NavigationGuard;
  meta: any;
  props: boolean | Object | Function | Dictionary<boolean | Object | Function>;
}
复制代码

结合代码里的实际数据对照理解各个属性的含义:

key value
path 传入的路径值
regex 根据path生成的正则匹配规则
components path对应的组件
instances 执行路由守卫方法时传入的route实例
name route的name
parent route的父级,是一个递归的对象,从最底层一直到最顶层,无则为undefined
redirect 重定向的路径
matchAs 用于匹配alias
props 传入路由的参数

结合以上解释,咱们能够得出vue-router一个大概的运行概念。

  1. 执行new Router()生成路由配置对象routedRecord

  2. 路由匹配根据route对象的regex进行匹配

  3. 根据routeparent对象递归获取component组件生成render Tree

  4. 执行各组件对应的导航守卫方法

此文大概简述了vue-router是如何执行的,可是对于router跳转的具体执行并无进行深刻解释,下一篇文章将会详细说明router跳转以后是如何执行。

相关文章
相关标签/搜索