1. 程式人生 > >vue-router 前端路由框架掃盲

vue-router 前端路由框架掃盲

    vue-router是一個與vue核心深度整合的前端路由框架。路由這個詞對大家來說其實並不陌生,我們用傳統的web專案來舉個例子。如下圖所示,這是一個左側為選單,右側為功能頁面的一個首頁效果。此時的路由為:投訴舉報/我的批次/批次管理/列表。如果我們要實現這樣一個效果,會將紅框的部分設定為一個<iframe/>標籤,然後通過選單的點選事件去切換iframe的連結,一般來說每一個連結返回的都是一段由服務端通過jsp等模板語言渲染出來的html文字。整個應用根據路由的層級,會形成iframe的樹形巢狀。

而前端發展到現在,整個介面已經在vue這樣的框架下實現了元件化,並且服務端不再承擔將資料渲染為HTML的任務,資料到介面的渲染由vue這種前端框架來完成,服務端只提供rest介面,為前端提供json格式的資料。前端完全元件化後,將形成一個元件樹,如下圖:

路由功能由傳統的頁面切換轉變為元件的切換,比如點選“列表頁面”元件上的新建按鈕,會將當前的“列表頁面”元件切換為“新建頁面元件”。整個應用將不存在頁面的切換,也就是所謂的單頁應用。vue-router就是一個管理路由,並根據路由狀態,切換元件的一個框架。

路由的管理:

vue-router對路由的管理是由一個router物件來完成,其中path對路由進行命名(':'後面代表引數),component指定了<route-view>要切換到的元件,children指定了路由的巢狀關係。

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id', component: User,
      children: [
        { path: 'profiles', component: Profiles},
        { path: 'posts', component: Posts}
      ]
    }
  ]
})

將這個router物件繫結到某個元件上,它將控制該元件及其子元件的路由狀態,並且該元件的<router-view>,成為根<router-view>。

const app = new Vue({
  router: router
})

在命名方面,以‘/’開頭的path,都視作為根path,也就是說path可以與ui層級不相符。並且vue-router提供了別名功能。如下面/home/foo和/foo是同一個路由狀態,即Home>Foo。

routes: [
    { path: '/home', component: Home,
      children: [
        // absolute alias
        { path: 'foo', component: Foo, alias: '/foo' },
        // relative alias (alias to /home/bar-alias)
        { path: 'bar', component: Bar, alias: 'bar-alias' },
        // multiple aliases
        { path: 'baz', component: Baz, alias: ['/baz', 'baz-alias'] }
      ]
    }
]

此外vue-router還提供了靈活的重定向功能,redirect是個函式,意味著你可以對重定向實現一些動態的操作,比如把當前已登入的賬號作為引數拼到重定向的path中。

routes: [
  { path: '/a', redirect: to => {
    // 方法接收 目標路由 作為引數
    // return 重定向的 字串路徑/路徑物件
  }}
]

路由的切換:

從表面上來看,路由的切換就是一次狀態的轉變,由a/b/c轉變為a/b/d。vue-router將轉換的動作及其實現封裝為一個push函式,在切換過程中,path的匹配邏輯,以及元件的切換邏輯都由router實現,呼叫者只需要關注路由的狀態,指定一個目標path。

在切換過程中router首先要對目標path進行匹配,以‘/’開頭的path,都被作為根path,如下面程式碼中存在三個根path:/home, /foo, 和/baz。

routes: [
    { path: '/home', component: Home,
      children: [
        // absolute alias
        { path: 'foo', component: Foo, alias: '/foo' },
        // relative alias (alias to /home/bar-alias)
        { path: 'bar', component: Bar, alias: 'bar-alias' },
        // multiple aliases
        { path: 'baz', component: Baz, alias: ['/baz', 'baz-alias'] }
      ]
    }
]

當執行this.$router.push({path: '/xx/xx/xx'})時,會從以上的三個根path開始匹配。path得到成功匹配後,router-view就會按照巢狀層級切換到對應的元件上。比如this.$router.push({path: '/home/foo'}),會切換到Home>Foo這個狀態,如下圖。當然this.$router.push({path: '/foo'})也是這個結果。

+-----------------------+
| Home                  |
|                       |
|  +-----------------+  |
|  | Foo             |  |
|  |                 |  |
|  |                 |  |
|  +-----------------+  |
|                       |
+-----------------------+

HOOK:

路由的切換過程雖然被封裝了,但開發者遇到某些情況時,仍然需要在路由切換過程中加入自己的操作,比如每次路由都校驗一下許可權。vue-route提供了一個hook機制(導航守衛)。hook的作用範圍有全域性的和區域性的,beforeEach和afterEach是全域性的,beforeRouteEnter,beforeRouteLeave,beforeRouteUpdate是元件內部的。

此外vue-router還對路由切換的過渡動畫效果進行了封裝,並且可以動態的設定:

<transition :name="transitionName">
  <router-view></router-view>
</transition>

路由傳參:

引數可以在url的path中

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id', component: User,
    }
  ]
})
router.push('/user/admin')

可以在url的query中

const router = new VueRouter({
  routes: [
    { path: '/user', component: User, props: (route) => ({ id: route.query.id }) }
  ]
})
router.push(/user?id=admin)