vue-router - 动态路径参数
有时候我们会有多个路由,它们的 URL 形式可能不完全相同,但是它们的功能或者需要渲染的内容是相同的,因此这些路由都需要映射到同一个组件上进行处理
在这种情况下,我们可以使用 Vue Router 的动态路由功能,将这些路由与同一个组件相关联
// 此时像/users/johnny 和 /users/jolyne 这类路由都会匹配到User这个组件
const routes = [
// 动态字段以冒号开始 在这里动态路由参数就是:id
// 动态路径参数 又被称之为params参数
{ path: '/users/:id', component: User },
]
动态路径参数 用冒号 :
表示
当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params
的形式暴露出来
const User = {
template: '<div>User {{ $route.params.id }}</div>',
}
你可以在同一个路由中设置有多个 路径参数,它们会映射到 $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
等
监听路由参数的改变
在使用带有参数的路由时需要注意,如果用户从 /users/johnny
导航到 /users/jolyne
,那么将会重复使用同一个组件实例
因为这两个路由都会渲染同一个组件,为了提高性能,Vue Router 会尽可能地复用组件实例而不是销毁再创建。然而,这也意味着组件的生命周期钩子不会被调用
如果需要在同一个组件中对参数的变化做出响应,可以通过在组件中使用 watch 或 computed 属性来监视 $route 对象上的参数变化
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)
},
}
404 Not found
Vue Router 使用常规参数来匹配 URL 片段之间的字符,这些片段由斜杠(/)分隔
如果我们想要匹配任意路径,我们可以使用自定义的正则表达式来定义路径参数
即在路径参数后面的括号中,我们可以加入正则表达式,以进行高级路由匹配
const routes = [
// 匹配以user-开头的路径
// 如路径为 /user-abc,$route.params.afterUser的值为abc
{ path: '/user-:afterUser(.*)', component: UserGeneric },
// 会匹配没有被之前路由捕获的所有路径
// 如路径为 /foo/bar/baz 会匹配到NotFound,$route.params.pathMatch的值为/foo/bar/baz
{ path: '/:pathMatch(.*)', name: 'NotFound', component: NotFound },
// 如路径为 /foo/bar/baz 会匹配到NotFound,$route.params.pathMatch的值为 ['foo', 'bar', 'baz']
// { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
]
this.$router.push({
name: 'NotFound',
// 保留当前路径并删除第一个字符,以避免目标 URL 以 `//` 开头。
params: { pathMatch: this.$route.path.substring(1).split('/') },
// 保留现有的查询和 hash 值,如果有的话
query: this.$route.query,
hash: this.$route.hash,
})
命名路由
除了 path
之外,你还可以为任何路由提供一个唯一的 name
因为name必须是唯一的,所以如果每一个路由都是命名路由的时候,路由的先后顺序就变得没有那么重要了
const routes = [
{
path: '/user/:username',
name: 'user',
component: User,
}
]
要链接到一个命名的路由,可以向 router-link
组件的 to
属性传递一个对象:
<!-- 通过params选项传入的参数会自动编解码 -->
<router-link :to="{ name: 'user', params: { username: 'erina' }}">
User
</router-link>
这跟代码调用 router.push()
是一回事
router.push({ name: 'user', params: { username: 'erina' } })
嵌套路由
一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构
/user/johnny/profile /user/johnny/posts
+------------------+ +-----------------+
| User | | User |
| +--------------+ | | +-------------+ |
| | Profile | | +------------> | | Posts | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+
一个被渲染的组件也可以包含自己嵌套的 <router-view>
。例如,如果我们在 User
组件的模板内添加一个 <router-view>
:
const User = {
template: `
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view></router-view>
</div>
`,
}
要将组件渲染到这个嵌套的 router-view
中,我们需要在路由中配置 children
:
const routes = [
{
path: '/user/:id',
// 当/user/:id 匹配成功
// 会渲染User组件
component: User,
// 注意,以 / 开头的嵌套路径将被视为根路径,这允许我们利用组件嵌套,而不必使用嵌套的 URL
children: [
// 当 /user/:id 匹配成功,User组件内部的router-view会被渲染为UserHome
{ path: '', component: UserHome },
{
// 当 /user/:id/profile 匹配成功,User组件内部的router-view会被渲染为UserProfile
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功,User组件内部的router-view会被渲染为UserPosts
path: 'posts',
component: UserPosts,
},
],
},
]
转载自:https://juejin.cn/post/7248109163850727481