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。初期化が終了します。デフォルトページを表示します。
更新しています。。。。