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)