學習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跳轉以後是如何執行。

相關文章
相關標籤/搜索