創建一個路由實例的配置選項
使用 new Router 創建了一個新的路由實例,其配置項說明:
mode:路由模式,默認值 ‘hash’ 使用井號( # )作路由,值 ‘history’ 可利用 History API 來完成頁面跳轉且無須重新加載;
routes:具體的路由配置列表,用到的配置項說明:
path:路由的路徑;
name:路由的名稱;
component:對應的視圖組件;
通過注入路由器,我們可以在任何組件內通過 this.route 訪問當前路由
動態路由參數匹配
模式 | 匹配路徑 | $route.params |
---|---|---|
/user/:username | /user/evan | { username: ‘evan’ } |
/user/:username/post/:post_id | /user/evan/post/123 | { username: ‘evan’, post_id: ‘123’ } |
除了 route 對象還提供了其它有用的信息,例如,route.hash 等等
相應路由參數的變化
當使用路由參數時,例如從 /user/foo 導航到 /user/bar,原來的組件實例會被複用。因爲兩個路由都渲染同個組件,比起銷燬再創建,複用則顯得更加高效。不過,這也意味着組件的生命週期鉤子不會再被調用
複用組件時,想對路由參數的變化作出響應的話,你可以簡單地 watch (監測變化) $route 對象
const User1 = {
template: '...',
watch: {
'$route' (to, from) {
// 對路由變化作出響應...
}
}
}
//或者使用
const User2 = {
template: '...',
beforeRouteUpdate (to, from, next) {
// react to route changes...
// don't forget to call next()
}
}
路由匹配優先級
有時候,同一個路徑可以匹配多個路由,此時,匹配的優先級就按照路由的定義順序:誰先定義的,誰的優先級就最高
當使用通配符路由時,請確保路由的順序是正確的,也就是說含有通配符的路由應該放在最後
嵌套路由
const routes = [
{
path:'/user/:id',
component:()=>import('@/views/user/User'),
children:[
{
//默認子路由
// UserHome 會被渲染在 User 的 <router-view> 中
path:'',
name:'UserHome',
component:()=>import('@/views/user/UserHome'),
},
{
// 當 /user/:id/profile 匹配成功,
// UserProfile 會被渲染在 User 的 <router-view> 中
path:'profile',
name:'UserProfile',
component:()=>import('@/views/user/UserProfile'),
}
],
}
];
編程式的導航
聲明式 | 編程式 |
---|---|
<router-link :to="…"> | router.push(…) |
在 Vue 實例內部,你可以通過 router.push
router.push這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器後退按鈕時,則回到之前的 URL。
// 字符串
router.push('home')
// 對象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 帶查詢參數,變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意:如果提供了 path,params 會被忽略,同樣的規則也適用於 router-link 組件的 to 屬性
注意: 如果目的地和當前路由相同,只有參數發生了改變 (比如從一個用戶資料到另一個 /users/1 -> /users/2),你需要使用 beforeRouteUpdate 來響應這個變化 (比如抓取用戶信息)
router.replace 跟 router.push 很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄
聲明式 | 編程式 |
---|---|
<router-link :to="…" replace> | router.replace(…) |
router.go(n)這個方法的參數是一個整數,意思是在 history 記錄中向前或者後退多少步,類似 window.history.go(n)
命名路由
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
}
]
})
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
router.push({ name: 'user', params: { userId: 123 }})
重定向和路由別名
const router = new VueRouter({
routes: [
{
path: '/a',
redirect: '/b'
}
]
})
const router2 = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})
//別名的功能讓你可以自由地將 UI 結構映射到任意的 URL,而不是受限於配置的嵌套路由結構
路由組件傳參
在組件中使用 $route 會使之與其對應路由形成高度耦合,從而使組件只能在某些特定的 URL 上使用,限制了其靈活性
通過 props 解耦,如果 props 被設置爲 true,route.params 將會被設置爲組件屬性
導航守衛
記住參數或查詢的改變並不會觸發進入/離開的導航守衛。你可以通過觀察 $route 對象來應對這些變化,或使用 beforeRouteUpdate 的組件內守衛
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
to: Route: 即將要進入的目標 路由對象
from: Route: 當前導航正要離開的路由
next: Function: 一定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。
next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。
next(’/’) 或者 next({ path: ‘/’ }): 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。你可以向 next 傳遞任意位置對象,且允許設置諸如 replace: true、name: ‘home’ 之類的選項以及任何用在 router-link 的 to prop 或 router.push 中的選項。
next(error): (2.4.0+) 如果傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 註冊過的回調。
確保要調用 next 方法,否則鉤子就不會被 resolved
全局後置鉤子
你也可以註冊全局後置鉤子,然而和守衛不同的是,這些鉤子不會接受 next 函數也不會改變導航本身
router.afterEach((to, from) => {
// ...
})
路由獨享守衛
在路由配置上直接定義 beforeEnter 守衛
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
組件內的守衛
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應路由被 confirm 前調用
// 不!能!獲取組件實例 `this`
// 因爲當守衛執行前,組件實例還沒被創建
},
beforeRouteUpdate (to, from, next) {
// 在當前路由改變,但是該組件被複用時調用
// 舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
// 由於會渲染同樣的 Foo 組件,因此組件實例會被複用。而這個鉤子就會在這個情況下被調用。
// 可以訪問組件實例 `this`
},
beforeRouteLeave (to, from, next) {
// 導航離開該組件的對應路由時調用
// 可以訪問組件實例 `this`
}
}
路由元信息
路由過渡動效
數據獲取
有時候,進入某個路由後,需要從服務器獲取數據。例如,在渲染用戶信息時,你需要從服務器獲取用戶的數據。我們可以通過兩種方式來實現:
導航完成之後獲取:先完成導航,然後在接下來的組件生命週期鉤子中獲取數據。在數據獲取期間顯示“加載中”之類的指示。
導航完成之前獲取:導航完成前,在路由進入的守衛中獲取數據,在數據獲取成功後執行導航。
從技術角度講,兩種方式都不錯 —— 就看你想要的用戶體驗是哪種。
滾動行爲
// 指定滾動行爲
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
// 有錨點時,滾動到錨點
return { selector: to.hash }
} else if (savedPosition) {
// 有保存位置時,滾動到保存位置
return savedPosition
} else {
// 默認滾動到頁面頂部
return { x: 0, y: 0 }
}
}
路由懶加載
導航守衛
導航守衛分爲全局導航守衛和路由導航守衛
router.beforeEach((to, from, next) => {
/* must call `next` */
})
router.beforeResolve((to, from, next) => {
/* must call `next` */
})
router.afterEach((to, from) => {})
//組件內的守衛
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave