动态路由
动态路由匹配
如果需要把不同路径的路由全都映射到同一个组件,例如,有一个 User
组件,对于所有 ID
各不相同的用户,都要使用这个组件来渲染,则可以在 vue-router 的路由路径中使用 “动态路径参数” (Dynamic Segment)来达到这个效果,如示例代码7-3-1所示。
<p>
<router-link to="/user/1">用户1</router-link>
<router-link to="/user/2">用户2</router-link>
</p>
<router-view></router-view>
const User = {
template: '<div>用户id:{{$route.params.id}}</div>'
}
// 配置路由信息
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes: [
{ path: '/user/:id', component: User }
]
})
通过 :id
的方式可以指定路由的路径参数,使用冒号来标识。这样 “/user/1”
和 “/user/2”
都可以匹配到 User
这个组件。在 User
组件插值表达式中使用 $route.params.id
可以获取这个 id
参数。如果是在方法中使用,则可以使用 this.$route.params.id
,注意是 $route
而不是 $router
。
另外,也可以在一个路由中设置多段路径参数,对应的值都会设置到 $route.params
中,如图7-2所示。
模式 |
匹配路径 |
$route.params |
/user/:username |
/user/evan |
{username: 'evan'} |
/user/:username/post/:post_id |
/user/evan/post/123 |
{username: 'evan', post_id: '123'} |
使用这种路径参数的方式是在页面切换时直接传递参数,可以让 URL 地址更加简洁,也更符合 RESTful 风格。
如果想实现更高级的正则路径匹配,vue-router 也是支持的,例如下面的代码:
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes: [
// 正则匹配,id为数字的路径
{ path: '/user/:id(\\d+)', component: User },
]
})
注意,在 Vue Router 4 中,移除了对于 *
路径正则匹配所有路径的方式,如果想要实现通配符匹配所有路径,可以通过参数 *
的方式实现,代码如下:
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes: [
// 不再支持
{ path: '*', component: User },
// 匹配/、/one、/one/two、/one/two/three任意字符
{ path: '/:chapters*', component: User },
]
})
当使用参数 *
的方式来匹配时,/
后面的所有字符都会被当作 chapters 参数,代码如下:
<router-link to="/userabc/efg/1">用户1</router-link>
{ path: '/:chapters*', component: User },
{{$route.params.chapters}}// [ "userabc", "efg", "1" ]
响应路由变化
当使用路由来实现页面切换时,有时需要能够监听到这些切换的事件,例如从 /page1
切换到 /page2
时,可以使用监听属性来获取这个事件,如示例代码7-3-2所示。
watch:{
// to表示切换之后的路由,from表示切换之前的路由
'$route'(to,from){
// 在这里处理响应
console.log(to,from)
}
}
可以使用 watch
监听属性来监听组件内部的 $route
属性,当路由发生变化时,便会触发这个属性对应的方法,有两种情况需要注意一下:
-
当路由切换对应的是同一个子组件时,例如上面的
User
组件,只是参数id
不同,那么监听方法可以写在子组件User
中。 -
当路由切换对应的是不同的组件时,例如上面的
PageOne
和PageTwo
组件,那么监听方法需要写在根组件中才可以接收到变化。
两种写法代码如下:
const User = {
template: '<div>用户id:{{$route.params.id}}</div>',
watch:{// 子组件watch方法
'$route'(to,from){ ... }
}
}
...
const app = Vue.createApp({
watch:{ // 根组件watch方法
'$route'(to,from){ console.log(to,from) }
}
})
设置在根组件的 watch
方法在上面两种情况下都会触发,所以建议统一在根组件中设置 watch
监听路由的变化。除了使用 watch
方法来监听路由的变化外,在 Vue Router 2.2 版本之后,引入了新的方案,叫作导航守卫。