需求
需要將給定匹配模式的路由映射到同一個組件。例如,我們可能有一個?User
?組件,它應該對所有用戶進行渲染,但用戶 ID 不同。在 Vue Router 中,我們可以在路徑中使用一個動態字段來實現,我們稱之為?路徑參數?:
const User = {template: '<div>User</div>',
}// 這些都會傳遞給 `createRouter`
const routes = [// 動態字段以冒號開始{ path: '/users/:id', component: User },
]
現在像?/users/johnny
?和?/users/jolyne
?這樣的 URL 都會映射到同一個路由。
路徑參數?用冒號?:
?表示。當一個路由被匹配時,它的?params?的值將在每個組件中以?this.$route.params
?的形式暴露出來。因此,我們可以通過更新?User
?的模板來呈現當前的用戶。
你可以在同一個路由中設置有多個?路徑參數,它們會映射到?$route.params
?上的相應字段。例如:
匹配模式 | 匹配路徑 | $route.params |
---|---|---|
/users/:username | /users/eduardo | { username: 'eduardo' } |
/users/:username/posts/:postId | /users/eduardo/posts/123 | { username: 'eduardo', postId: '123' } |
除了?$route.params
?之外,$route
?對象還公開了其他有用的信息,如?$route.query
(如果 URL 中存在參數)、$route.hash
?等。你可以在?API 參考中查看完整的細節。
實例
import { createRouter, createWebHistory } from 'vue-router'
import UserPost from './views/UserPost.vue'export const router = createRouter({history: createWebHistory(),routes: [{ path: '/users/:username/posts/:postId', component: UserPost }],
})// html
<template><ul><li><router-link to="/users/eduardo/posts/1">/users/eduardo/posts/1</router-link></li><li><router-link to="/users/eduardo/posts/20">/users/eduardo/posts/20</router-link></li></ul><router-view></router-view>
</template><script>
export default {name: "App",
};
</script>
1、響應路由的參數變化
使用帶有參數的路由時需要注意的是,當用戶從?/users/johnny
?導航到?/users/jolyne
?時,相同的組件實例將被重復使用。因為兩個路由都渲染同個組件,比起銷毀再創建,復用則顯得更加高效。不過,這也意味著組件的生命周期鉤子不會被調用。
要對同一個組件中參數的變化做出響應的話,你可以簡單地 watch?$route
?對象上的任意屬性,在這個場景中,就是?$route.params
?:
const User = {template: '...',created() {this.$watch(() => this.$route.params,(toParams, previousParams) => {// 對路由變化做出響應...})},
}
?或者,使用?beforeRouteUpdate
?導航守衛,它也可以取消導航:
const User = {template: '...',async beforeRouteUpdate(to, from) {// 對路由變化做出響應...this.userData = await fetchUser(to.params.id)},
}
2、捕獲所有的路由或者404 Not found 路由
常規參數只匹配 url 片段之間的字符,用?/
?分隔。如果我們想匹配任意路徑,我們可以使用自定義的?路徑參數?正則表達式,在?路徑參數?后面的括號中加入 正則表達式 :
js
const routes = [// 將匹配所有內容并將其放在 `$route.params.pathMatch` 下{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },// 將匹配以 `/user-` 開頭的所有內容,并將其放在 `$route.params.afterUser` 下{ path: '/user-:afterUser(.*)', component: UserGeneric },
]
在這個特定的場景中,我們在括號之間使用了自定義正則表達式,并將pathMatch
?參數標記為可選可重復。這樣做是為了讓我們在需要的時候,可以通過將?path
?拆分成一個數組,直接導航到路由:
js
this.$router.push({name: 'NotFound',// 保留當前路徑并刪除第一個字符,以避免目標 URL 以 `//` 開頭。params: { pathMatch: this.$route.path.substring(1).split('/') },// 保留現有的查詢和 hash 值,如果有的話query: this.$route.query,hash: this.$route.hash,
})
如果你正在使用歷史模式,請務必按照說明正確配置你的服務器。
3、高級匹配模式?
Vue Router 使用自己的路徑匹配語法,其靈感來自于?express
,因此它支持許多高級匹配模式,如可選的參數,零或多個 / 一個或多個,甚至自定義的正則匹配規則。