Vue-Router 源碼學習之咱們從API中看些門道

前言

此次真的是過久過久沒見了,夥伴們。 學習真的沒有鬆懈,只是季度末要衝一衝績效,一會兒把時間都充值了。(ps:我看應該是個人腦子須要充值)前端

系列文章: Vue-Router源碼分析之index.jsvue

Vue-Router源碼分析之install方法面試

正文

爲何要從API中看門道呢?

咱們在使用vue-router的時候,其實就是按照API進行操做,源碼其實就是API的另外一種形式,在個人學習中,我發現一味的乾貨有時效果並很差,由其是深刻思考性比較強的內容。所以本篇文章因此做爲一個過渡章節,讓咱們一塊兒聊一聊承上啓下的內容,聊聊API:vue-router

咱們的push有哪些狀況?

在實際工做中,編程式導航要比<router-link>標籤使用的多的多,複雜邏輯中嵌套路由跳轉都是要使用編程式導航。編程

// 字符串
router.push('home')
// 對象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
router.push({ path: `/user/${userId}` })
// 帶查詢參數,變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
複製代碼

在編程式路由中,咱們能夠接收一個對象、一個字符串,對象的key有path、name、query、params等等,可是須要相互組合。數組

這麼多狀況vue-router要對push這麼多狀況作一個處理,咱們push接收的參數的類型是什麼?用flow設定爲Location、RawLocationapp

用flow.js設定的類型
declare type Location = {
  _normalized?: boolean;
  name?: string;
  path?: string;
  hash?: string;
  query?: Dictionary<string>;
  params?: Dictionary<string>;
  append?: boolean;
  replace?: boolean;
}
declare type RawLocation = string | Location
複製代碼

翻譯過來就是未處理的、生的路徑。因此咱們的push操做傳遞的是一個生冷的路徑,通過一次match的處理源碼分析

源碼內容:
const route = this.router.match(location, this.current)
複製代碼

變成vue-router所須要的結構,route類型post

declare type Route = {
  path: string;
  name: ?string;
  hash: string;
  query: Dictionary<string>;
  params: Dictionary<string>;
  fullPath: string;
  matched: Array<RouteRecord>;
  redirectedFrom?: string;
  meta?: any;
}
複製代碼

因此從API結合表層源碼來看,咱們在進行編程式導航時的過程,先將未處理的路徑(ps:vue-router對這種未處理路徑無法直接進行跳轉等操做)處理成一個規範的route類型,而後進行具體的路由跳轉內容。學習

命名路由與視圖

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})
複製代碼

一個組件內能夠有多個router-view組件,我接觸的幾個項目都是維護一個根結點的router-view。大部分都是這種結構

<template>
  <div id="app">
    <router-view/>
  </div>
</template>
複製代碼

咱們一個路徑下能夠展現多個路由視圖組件嗎?

答案固然是確定的,官方的命名視圖的例子(jsfiddle.net/posva/22wgk… 能夠看到,咱們在同一個路徑下能夠放置多個<router-link>,這裏面的name與咱們在構造vue-router時設置的components有對應,咱們通常都是component : xxx;對應一個組件。如何對應多個的呢?

源碼內容:
components: route.components || { default: route.component },
複製代碼

其實人家自己但願你用components,你要只用一我的家就給你包裝成一個map,key呢就是默認值的意思。

再看看咱們的vue-router2開始的路由守衛

路由守衛有哪些呢?

  • 1:全局的beforeEach

  • 2:單個路由配置的beforeEnter

  • 3:全局的afterEach

  • 4:組件內的路由守衛:

    beforeRouteEnter

    beforeRouteUpdate (2.2 新增)

    beforeRouteLeave

  • 5:全局的beforeResolve(vue-router2.5新增)

別的守衛還有嗎?這麼看來是沒有了。

全局的beforeEnter、afterEach、beforeResolve爲何會做用在每個路由配置中呢?在index一章中,咱們有三個存放守衛的數組你們還有印象嗎?

beforeHooks: Array<?NavigationGuard>;
resolveHooks: Array<?NavigationGuard>;
afterHooks: Array<?AfterNavigationHook>;
複製代碼

在router實例中存儲這些。因此咱們在作路由跳轉的時候能夠拿到這些守衛,其他的守衛怎麼辦?只好在跳轉的時候具體狀況具體執行,

守衛分爲三個種類:

1:離開組件以前,2:進入組件(先後都有守衛) 3:更新組件以前

因此一個路由的跳轉必定伴隨着如下幾個步驟

  • 1:跳轉咱們稱之爲transitionTo

  • 2:那麼跳轉中進行一個confirmTransiton(跳轉前的準備)

  • 3:跳轉結束時進行一個updateRoute的過程

上文提到的confirmTransition:先收集到全部的守衛,把前置守衛們(前置!!!)鏈接成一個數組,跳轉前挨個執行,前置守衛執行完怎麼辦?都經過來,那就更新當前路由,更新完當前路由就執行一下後置守衛。 vue-router源碼中:

核心的路由跳轉方法就是transitionTo: 具體內容是由confirmTransition與updateRoute實現的

其他的一些這這那那的容錯,並不影響主流程。

總結一下

對於push、replace傳遞的未處理的路徑,進行處理成vue-router能夠操做的路徑。

對於多個router-view,咱們能夠選擇children,components來實現。

路由守衛爲何能夠有全局的,每一個路由均可以用,由於在router實例上,咱們每次跳轉均可以找到。

路由跳轉經歷了confirm確認與update更新兩步

結束語

中秋節剛剛過去,十一立刻就到了

沒有來得及給你們帶來祝福,但願你們十一的時候每次路由跳轉都不堵車!

每個前端er(boy and girl) 大家都不是一我的在戰鬥

我是一個應屆生,最近和朋友們維護了一個公衆號,內容是咱們在從應屆生過渡到開發這一路所踩過的坑,已經咱們一步步學習的記錄,若是感興趣的朋友能夠關注一下,一同加油~

我的公衆號:IT面試填坑小分隊
相關文章
相關標籤/搜索