1. 前言
vue-router版本:3.3.2
vue-router倉庫:https://github.com/vuejs/vue-router
vue-router文檔:https://router.vuejs.org/zh/
文章時間:2020-06-16
2 執行順序
首先看個簡單的代碼塊,看看vue-router是怎么注冊到vue實例上:
// 1.注冊VueRouter
Vue.use(VueRouter);
// 2.創建路由組件並設置路由
const router = new VueRouter({
mode: 'hash',
routes: [
{ path: '/', component: Home }
]
});
// 3.創建Vue實例
window.vueInstance = new Vue({
el: '#app',
router
});
2.1 第一步:Vue.use(VueRouter)
調用此代碼時,實際執行的vue-router/src/install.js,其內部主要執行的代碼步驟如下:
1) 設置Vue.prototype.$router屬性,返回值為_router對象(全局VueRouter對象);
2) 設置Vue.prototype.$route屬性,返回值為_route對象(當前頁面的route對象);
3) 注冊全局組件:router-view;
4) 注冊全局組件:router-link;
5) 在Vue.beforeCreate事件上注入回調函數,此回調函數的執行在第三步 new Vue({router})上才觸發。
2.2 第二步:new VueRouter({options})
這一步是生成VueRouter對象,其調用的構造函數內部代碼執行步驟如下:
1) 創建this.matcher,進行如下操作:
①創建pathList:路由的所有path集合,並把'*'號路徑的路由移到pathList的最后。
②創建pathMap:key為路由的path,item為封裝了的對應的RouteRecord對象,包括path、path對應的regex、components、name等等。
③創建nameMap:key為路由的name,item與pathMap一樣,都是RouteRecord對象。
④this.matcher提供了2個方法:match和addRoutes。
2) 創建this.history,此屬性根據options.mode設置不同的導航模式:
①若mode == 'history' :表示采用HTML5 History模式。
②若mode == 'hash' :表示采用hash模式,默認為此模式。
③若mode == 'abstract' :支持所有 JavaScript 運行環境,如 Node.js 服務器端。
2.3 第三步:new Vue({ router })
這里主要是為了執行第一步的Vue.use(router)注入的beforeCreate回調。
其主要執行router.init()方法,內部步驟如下:
1) 當前router對象緩存創建的Vue實例
this.apps.push(app); this.app = app;
2) 根據當前頁面的url獲取對應的Route對象並渲染匹配的組件頁面,其內部步驟如下:
假設url為http://localhost:8080/hash-mode/#/bar?a=1#title,model為'hash'
①獲取路徑;值為:/bar?a=1#title
②解析路徑,得到路徑完整信息;值為:{ hash: "#title", params: {}, path: "/bar", query: {a: "1"}, _normalized: true }
③根據上面的path,找到之前存儲的RouteRecord對象,創建為Route對象。
④調用離開組件的beforeRouteLeave守衛;若當前的url改變是從組件a→組件b,這適合調用a組件的beforeRouteLeave守衛回調。
⑤調用全局Router的beforeEach守衛;
⑥調用重用組件里的beforeRouteUpdate守衛;
⑦在路由配置里調用beforeEnter守衛。
⑧對路由配置里對應的異步組件進行解析;路由配置的組件通過 require.ensure() 或 Promise.resolve() 加載的組件才會執行這一步。
⑨調用進入組件里的beforeRouteEnter守衛;
⑩調用全局Router的beforeResolve守衛;
⑪導航被確認;修改當前的route為新頁面的route;
⑫調用全局Router的afterEach守衛;
3) 在winodw的popstate事件上注冊回調,執行上一步操作( 執行第2步)。
注意:哪怕模式選擇的是'hash',當window擁有'popstate'事件時也會采用此事件,沒有的話才采用'hashchange'事件。為什么呢?因為'popstate'在IE上是不支持,'hashchange'從IE8開始支持。
4) 在Vue的destroyed鈎子注冊回調:注銷第4步在window注冊的回調。
