摘要:而組件在創(chuàng)建時,又怎么會去調(diào)用呢這是由于將自身作為一個插件安裝到了,通過注冊了一個鉤子函數(shù),從而在之后所有的組件創(chuàng)建時都會調(diào)用該鉤子函數(shù),給了檢查是否有參數(shù),從而進行初始化的機會。
vue-router 是 Vue.js 官方的路由庫,本著學習的目的,我對 vue-router 的源碼進行了閱讀和分析,分享出來給其他感興趣的同學做個參考吧。
參考源碼:vuejs/vue-router v2.2.1 - github
文檔:vue-router 官方中文教程
初步我們分別從不同的視角來看 vue-router。
從開發(fā)者角度來看,是這樣的:
var router = new VueRouter({ routes: [ {path: "/foo", component: {template: "FOO"}}, {path: "/bar", component: {template: "BAR"}} ] }) var vm = new Vue({ el: "#app", router: router })
我們創(chuàng)建一個 router,傳入的 routes 中的每一項即為一條路由(route)配置,表示在匹配給定的地址時,應(yīng)該使用什么組件渲染視圖。
將 router 傳入 new Vue() 用于創(chuàng)建根組件,這樣根組件中對應(yīng)的視圖區(qū)域,可以基于 router 中的配置,根據(jù)頁面地址顯示不同的內(nèi)容。當然,這還需要在組件模板中使用
從視圖角度來看,是這樣的:
......
頁面地址變更后,
從數(shù)據(jù)角度來看,是這樣的:
vm + _router | $router - history - matcher + _route | $route - matched
vm.$router 引用當前組件對應(yīng)的 router 對象,該對象在初始化時(在 vm 創(chuàng)建過程中執(zhí)行初始化),會啟動對頁面地址變更的監(jiān)聽,從而在變更時更新 vm 的數(shù)據(jù)($route),進而觸發(fā)視圖的更新。
深入如何實現(xiàn)對地址變更的監(jiān)聽?
對于缺省的 HashHistory 模式(也就是基于頁面地址的 hash 部分來實現(xiàn)路由功能,如 http://example.com/path#/foo、http://example.com/path#/bar),是通過監(jiān)聽 hashChange 事件來實現(xiàn):
window.addEventListener("hashchange", () => { // this.transitionTo(...) })
源碼
這個動作是什么時候執(zhí)行的呢?
是在 router.init()(源碼)中調(diào)用的,而 router.init() 則是在根組件創(chuàng)建時(源碼)調(diào)用的。
而 Vue 組件在創(chuàng)建時,又怎么會去調(diào)用 router.init() 呢?
這是由于 vue-router 將自身作為一個插件安裝到了 Vue,通過 Vue.mixin() 注冊了一個 beforeCreate() 鉤子函數(shù),從而在之后所有的 Vue 組件創(chuàng)建時都會調(diào)用該鉤子函數(shù),給了檢查是否有 router 參數(shù),從而進行初始化的機會。進而通過層層調(diào)用執(zhí)行了監(jiān)聽 hashchange 事件的動作。
整理一下:
new Vue()
執(zhí)行 vue-router 注入的 beforeCreate 鉤子函數(shù)
執(zhí)行 router.init(vm)
執(zhí)行 history.setupListeners(),注冊事件監(jiān)聽
地址變更如何通知到 vm?
這個過程比較簡單,hashchange 時,執(zhí)行 history.transitionTo(...),在這個過程中,會進行地址匹配,得到一個對應(yīng)當前地址的 route,然后將其設(shè)置到對應(yīng)的 vm._route 上。
只是進行了賦值,為什么 vm 就可以感知到路由的改變了呢?
答案在 vue-router 注入 Vue 的 beforeCreate 鉤子函數(shù)中(源碼):
Vue.util.defineReactive(this, "_route", this._router.history.current)
采用與 Vue 本身數(shù)據(jù)相同的“數(shù)據(jù)劫持”方式,這樣對 vm._route 的賦值會被 Vue 攔截到,并且觸發(fā) Vue 組件的更新渲染流程。
地址變更如果同步視圖更新?
接上一步,vm._route 已經(jīng)接收到路由的變更,從而觸發(fā)視圖更新。而當視圖更新進一步調(diào)用到
這里的主要處理邏輯是從根組件中取出當前的路由對象(parent.$route),然后取得該路由下對應(yīng)的組件,然后交由該組件進行渲染:
return h(component, data, children)
這其中還涉及
其實 vue-router 從
vue-router 以插件方式“侵入”Vue,從而支持一個額外的 router 屬性,以提供監(jiān)聽并改變組件路由數(shù)據(jù)的能力。這樣每次路由發(fā)生改變后,可以同步到數(shù)據(jù),進而“響應(yīng)式”地觸發(fā)組件的更新。
路由變更到視圖變更的過程整理為:
hashchange --> match route --> set vm._route -->render() --> render matched component
實現(xiàn)過程中的技術(shù)點包括:
Vue 插件機制
響應(yīng)式數(shù)據(jù)機制
Vue 渲染機制
地址變更監(jiān)聽
最后我寫了一個應(yīng)用 Vue.js、vue-router 以及其他 Vue 相關(guān)工具(Vuex、vue-loader)的示例,感興趣可以看下:luobotang/vue-demo - github。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/88202.html
摘要:本文假設(shè)讀者手里有關(guān)于和的文檔,并且對和有一定的了解。沒有文檔也沒關(guān)系我這里有關(guān)于文檔以及介紹,可以配合本文進行學習。關(guān)鍵就是在中部導航欄熱門,新上榜那塊,棕色框內(nèi)的內(nèi)容會根據(jù)中部導航欄選中不同內(nèi)容進行改變。 在這個教程里面,我會通過一系列的代碼和圖片來學習怎么使用vue-router,以及vuex。本文假設(shè)讀者手里有關(guān)于vue-router和Vuex的文檔,并且對Vue-router...
摘要:本文假設(shè)讀者手里有關(guān)于和的文檔,并且對和有一定的了解。沒有文檔也沒關(guān)系我這里有關(guān)于文檔以及介紹,可以配合本文進行學習。關(guān)鍵就是在中部導航欄熱門,新上榜那塊,棕色框內(nèi)的內(nèi)容會根據(jù)中部導航欄選中不同內(nèi)容進行改變。 在這個教程里面,我會通過一系列的代碼和圖片來學習怎么使用vue-router,以及vuex。本文假設(shè)讀者手里有關(guān)于vue-router和Vuex的文檔,并且對Vue-router...
摘要:使用值來作路由。原生應(yīng)用本身就是多頁的場景,頁面間狀態(tài)的隔離比共享更重要一些。使用開發(fā)的是原生應(yīng)用,頁面棧的管理使用的也是原生的特性,沒有但是有模塊可以實現(xiàn)頁面的前進和后退等操作。 系列文章的目錄在 ? 這里 (由于 我比較懶 最近一段時間在忙其他事,系列文章拖了好久終于又更新了。。。) 什么是 vue-router ? vue-router 官方文檔 vue-router 是針對 V...
閱讀 1198·2021-11-24 09:38
閱讀 2605·2021-09-27 14:00
閱讀 1165·2019-08-30 15:55
閱讀 1340·2019-08-30 14:16
閱讀 1492·2019-08-30 10:54
閱讀 2865·2019-08-28 17:58
閱讀 758·2019-08-26 13:22
閱讀 1234·2019-08-26 12:01