vue-router源碼閱讀(一) 內部探究,介紹vue-router的執行順序,new VueRouter({options})時做了什麼,new Vue({ router })內部又做了什麼等等。 ...
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註冊的回調。
End Web開發之路系列文章 菜單載入中...