ソースコードからVue-Routerの実装原理を理解する

vueを使用してシングルページ(SPA)アプリケーションを開発する場合、vue-routerは不可欠なテクノロジーです。その本質は、URLの変更を監視し、ルーティングルールを照合して、ページを更新せずに対応するページを表示することです。つまり、ビューを更新しますが、更新しないでください。ページを再リクエストしてください。

ソースコードを介してvue-routerの実装プロセス全体を見てみましょう。

1.Vue-routerソースディレクトリ構造

githubアドレス:https//github.com/vuejs/vue-router

現在のバージョン:
vue 2.6.11
vue-router 3.5.1

ここに画像の説明を挿入します

コンポーネント:ここに2つのコンポーネントと
履歴があります:これはルーティングモード(モード)です、
utilの3つの方法があります:ここにルーティング関数とクラスがあり
ますcreate-matcherとcreate-router-mapはルーティング分析と構成テーブル
インデックスの生成です: VueRouterクラスは
、プラグインインストール全体のエントリポイントでもあります。プラグインインストールメソッドを提供します

2つ目は、Vue.use()レジスタプラグインです。

Vueは、ルーティングを使用するときに登録するためにVue.use(plugin)メソッドを呼び出す必要があります。コードには、vueソースコードのsrc / core / global-api /use.jsファイルに2つの主要な関数があります。

1.繰り返し登録を回避するためのキャッシュ
2.プラグインのインストール方法を使用するか、プラグインを直接実行して登録します

// 初始化use
export function initUse (Vue: GlobalAPI) {
    
    
  Vue.use = function (plugin: Function | Object) {
    
    
    // 检测插件是否已经被安装
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    if (installedPlugins.indexOf(plugin) > -1) {
    
    
      return this
    }
    // additional parameters
    const args = toArray(arguments, 1)
    args.unshift(this)
    // 调用插件的 install 方法或者直接运行插件,以实现插件的 install
    if (typeof plugin.install === 'function') {
    
    
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
    
    
      plugin.apply(null, args)
    }
    installedPlugins.push(plugin)
    return this
  }
}
3、ルーティングインストールインストール

ルートを登録するときは、ルートのinstallメソッドを呼び出す必要があります。コードは、vue-routerのインストールプログラムであるvue-routerソースコードのsrc / install.jsファイルにあります。このメソッドは、次のことを行います。 4つのこと:

1.繰り返しインストールを回避するためのキャッシュ
2.Vue.mixinを使用してbeforeCreateと破棄されたフック関数を混合し、Vueライフサイクル中に呼び出されるようにします
3.すべてのコンポーネントの使用を容易にするためにVue.prototypeを介してルーターとルートのプロパティを定義します
4 。グローバル登録router-viewおよびrouter-linkコンポーネント。router-linkはルーティングの変更をトリガーするために使用され、router-viewは対応するルーティングビューの変更をトリガーするために使用されます。

import View from './components/view'
import Link from './components/link'
export let _Vue
// Vue.use安装插件时候需要暴露的install方法 
export function install (Vue) {
    
    
  // 判断是否已安装过,安装过直接 return 出来,没安装执行安装程序 
  if (install.installed && _Vue === Vue) return
  install.installed = true
  // 把Vue赋值给全局变量 
  _Vue = Vue
  // 判断是否已定义 
  const isDef = v => v !== undefined
  //通过registerRouteInstance方法注册router实例 
  const registerInstance = (vm, callVal) => {
    
    
    let i = vm.$options._parentVnode
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
    
    
      i(vm, callVal)
    }
  }
  // 混淆进Vue实例,在boforeCreate与destroyed钩子上混淆 
  Vue.mixin({
    
    
    beforeCreate () {
    
    
      // 在option上面存在router则代表是根组件 
      if (isDef(this.$options.router)) {
    
    
        // 根路由设置为自己
        this._routerRoot = this
        // 保存router
        this._router = this.$options.router
        // VueRouter对象的init方法 
        this._router.init(this)
        // Vue内部方法,为对象defineProperty上在变化时通知的属性,实现响应式
        Vue.util.defineReactive(this, '_route', this._router.history.current)
      } else {
    
    
        // 非根组件则直接从父组件中获取,用于 router-view 层级判断
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
      }
      // 通过registerRouteInstance方法注册router实例
      registerInstance(this, this)
    },
    destroyed () {
    
    
      registerInstance(this)
    }
  })
  //在Vue.prototype挂载属性,可以通过 this.$router、this.$route 来访问 Vue.prototype 上的 _router、_route
  Object.defineProperty(Vue.prototype, '$router', {
    
    
    get () {
    
     return this._routerRoot._router }
  })
  Object.defineProperty(Vue.prototype, '$route', {
    
    
    get () {
    
     return this._routerRoot._route }
  })
  // 注册router-view以及router-link组件 
  Vue.component('RouterView', View)
  Vue.component('RouterLink', Link)

  // 该对象保存了两个option合并的规则 
  const strats = Vue.config.optionMergeStrategies
  // use the same hook merging strategy for route hooks
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}
4、VueRouterのインスタンス化

ルーティングプラグインをインストールした後、VueRouterがインスタンス化され、vue-routerソースコードのsrc /index.jsファイルでVueインスタンスのオプションに渡されます。以下はVueRouterのコンストラクターです。

  constructor (options: RouterOptions = {
    
    }) {
    
    
    this.app = null
    this.apps = []
    this.options = options
    this.beforeHooks = []
    this.resolveHooks = []
    this.afterHooks = []
    // 路由匹配对象
    this.matcher = createMatcher(options.routes || [], this)
	// 根据 mode 采取不同的路由方式
    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}`)
        }
    }
  }

コンストラクターには2つの重要な点があります
。1。ルートマッチングオブジェクトマッチャー(コア)を作成する

2.モードに応じて異なるルーティング方法を取ります

1. Vue-routerには、ハッシュ、履歴、抽象の3つのルーティングモード(モード)があります。抽象は、weexなどの非ブラウザー環境で使用されるルーティングモード
です。2 。履歴が渡される場合、デフォルトはハッシュモードです。モードですが、現在の環境ではサポートされていないため、ハッシュモード
3にダウングレードされます。現在の環境が非ブラウザ環境の
場合は、抽象モード4を使用する必要があります。パターンが正常に一致した場合、対応する初期化操作が実行されます

5、ルーティング分析
6、ルーティングスイッチ
7、ルーティング同期
8、scrollBrhavior
、ルーティングコンポーネント

1. router-view:コンポーネントマウント
2. router-link:ルートジャンプ

最後に、ルーティングのプロセス

1. Vue.use(ルーター)登録
2.登録時に、installメソッドを呼び出してライフサイクルに組み込み、ルーターとルートの属性を定義し、router-viewコンポーネントとrouter-linkコンポーネントを登録します。3。
構成に従ってルーターインスタンスを生成します。 array(着信ルート)ルーティング構成レコードテーブルを生成し、さまざまなモードに従ってルーティングの変更を監視するHistoryオブジェクトを
生成します。4。vueインスタンスを生成し、ルーターインスタンスをvueインスタンスにマウントします。マウント時に、ルーターは最初に混合されたライフサイクル機能
。5。初期化が終了します。デフォルトページを表示します。

更新しています。

おすすめ

転載: blog.csdn.net/weixin_43299180/article/details/114932543