vue-router源碼詳解一

首發我的網站《鋒言鋒語》- vue-router源碼詳解一html

beforeCreate

在src/install.js文件中使用Vue.mixi混入兩個生命週期處理函數:beforeCreatedestroyed,在beforeCreate中處理了和rooter相關的操做:vue

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

this.$options.router

vue中有兩種vue對象:vue實例和vue組件,其中vue實例是經過new Vue建立的vue對象,vue組件是經過Vue.component建立的vue對象。
可是本質上「Vue組件是可複用的Vue實例」,而「vue實例是特殊的根vue組件」vue-router

參考資料:Vue 實例組件基礎api

vm.$options則是用於當前 Vue 實例的初始化選項。app

參考資料:實例屬性ide

所以只有在vue實例中,才傳入了router屬性:函數

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

new Vue({
  router,
}).$mount('#app')

所以在beforeCreate中的代碼,則是分別對根vue組件和普通vue組件作了_routerRoot的定義:網站

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
  }

咱們在組件中使用this.$router,就是返回_routerRoot_router屬性:ui

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

this.$route,就是返回_routerRoot_router屬性:this

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

this.$routethis.$router區別

經過beforeCreate中的代碼,能夠獲得:

  • this._router就是傳入的router屬性值,也就是new VueRouter返回的是VueRouter對象
  • this._routerRoot._route只是this._routerRoot._router中的history.current屬性值

接下來,咱們看一下this._router.history是一個什麼對象呢?

export default class VueRouter {
  constructor (options: RouterOptions = {}) {
    let mode = options.mode || 'hash'

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

經過VueRouter的構造函數能夠看出,this._router.history在不一樣的場景下表示不一樣的對象,HTML5HistoryHashHistoryAbstractHistory對象。

上述三種***History類都繼承於History類:

declare type Route = {
  path: string;
  name: ?string;
  hash: string;
  query: Dictionary<string>;
  params: Dictionary<string>;
  fullPath: string;
  matched: Array<RouteRecord>;
  redirectedFrom?: string;
  meta?: any;
}

export class History {
  current: Route
}

能夠看出,this.$route也即this._routerRoot._route就是當前頁面的url的一些基本屬性,而this.$router則是表明整個vue router對象,因此更多的是使用起pushreplacego等路由操做函數。

相關文章
相關標籤/搜索