带参数的动态路由匹配
很多时候,我们需要将具有给定模式的路由映射到同一个组件。例如,我们可能有一个 User
组件,它应该为所有用户渲染,但使用不同的用户 ID。在 Vue Router 中,我们可以使用路径中的动态段来实现这一点,我们称之为 _参数_
import User from './User.vue'
// these are passed to `createRouter`
const routes = [
// dynamic segments start with a colon
{ path: '/users/:id', component: User },
]
现在,像 /users/johnny
和 /users/jolyne
这样的 URL 都将映射到同一个路由。
一个 _参数_ 由冒号 :
表示。当路由匹配时,其 _参数_ 的值将作为 route.params
公开给每个组件。因此,我们可以通过将 User
的模板更新为以下内容来渲染当前用户 ID
<template>
<div>
<!-- The current route is accessible as $route in the template -->
User {{ $route.params.id }}
</div>
</template>
你可以在同一个路由中拥有多个 _参数_,它们将映射到 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 参考 中查看完整细节。
此示例的工作演示可以在 这里 找到。
对参数更改做出反应
使用带参数的路由时需要注意的一点是,当用户从 /users/johnny
导航到 /users/jolyne
时,**将重用同一个组件实例**。由于这两个路由都渲染同一个组件,因此这比销毁旧实例然后创建一个新实例更有效。**但是,这也意味着组件的生命周期钩子将不会被调用**。
要对同一个组件中的参数更改做出反应,你可以简单地观察 route
对象上的任何内容,在本例中是 route.params
<script setup>
import { watch } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
watch(
() => route.params.id,
(newId, oldId) => {
// react to route changes...
}
)
</script>
<script>
export default {
created() {
this.$watch(
() => this.$route.params.id,
(newId, oldId) => {
// react to route changes...
}
)
},
}
</script>
或者,使用 beforeRouteUpdate
导航守卫,它也允许你取消导航
<script setup>
import { onBeforeRouteUpdate } from 'vue-router'
// ...
onBeforeRouteUpdate(async (to, from) => {
// react to route changes...
userData.value = await fetchUser(to.params.id)
})
</script>
<script>
export default {
async beforeRouteUpdate(to, from) {
// react to route changes...
this.userData = await fetchUser(to.params.id)
},
// ...
}
</script>
捕获所有 / 404 未找到路由
常规参数只会匹配 URL 片段之间的字符,这些字符由 /
分隔。如果我们想匹配**任何内容**,我们可以使用自定义 _参数_ 正则表达式,方法是在 _参数_ 后面添加括号中的正则表达式
const routes = [
// will match everything and put it under `route.params.pathMatch`
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
// will match anything starting with `/user-` and put it under `route.params.afterUser`
{ path: '/user-:afterUser(.*)', component: UserGeneric },
]
在这种特定情况下,我们使用括号中的 自定义正则表达式 并将 pathMatch
参数标记为 可选可重复。这允许我们通过将 path
拆分为数组来直接导航到路由,如果需要的话
router.push({
name: 'NotFound',
// preserve current path and remove the first char to avoid the target URL starting with `//`
params: { pathMatch: route.path.substring(1).split('/') },
// preserve existing query and hash if any
query: route.query,
hash: route.hash,
})
在 可重复参数 部分中查看更多内容。
如果你使用的是 历史模式,请确保按照说明正确配置你的服务器。
高级匹配模式
Vue Router 使用自己的路径匹配语法,灵感来自 express
中使用的语法,因此它支持许多高级匹配模式,例如可选参数、零个或多个/一个或多个要求,甚至自定义正则表达式模式。请查看 高级匹配 文档以探索它们。