Vue Router(2)
带参数的动态路由匹配
很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 User 组件,它应该对所有用户进行渲染, 但用户ID不同。在Vue Router中,我们可以在路径中使用一个动态字段来实现,我们称之为路径参数
const User = { template: '<div> User </div>' } // 这些都会传递给 `createRouter` const routers = [ // 动态字段以冒号开始 { path: '/users/:id', component: User} ]
现在像 /users/johnny 和 /users/jolyne 这样的URL都会映射到同一个路由
路径参数 用冒号 : 表示, 当一个路由匹配时, 它的 params 的值将在每个组件中以 this.$route.params 的形式暴露出来。因此,我们可以通过更新Userd的模板来呈现当前用户ID
const User = { template: '<div>User {{ $route.params.id }}</div>', }
你可以在同一个路由中设置有多个路径参数, 它们会映射到 $route.params 上的相应字段。
例如:
/users/:username // /users/eduardo {username: 'eduardo'} /users/:username/posts/:postId // /users/eduardo/posts/123 {username: 'eduardo', postId:'123'}
除了 route 对象还公开了其他有用的信息,如 route.hash 等。
响应路由参数的变化
使用带有参数的路由时需要注意的时,当用户从 /users/johnny 导航到 /users/jolyne时 ,相同的组件实例将被重复使用。因为两个路由都渲染同一个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会被调用。
要对同一个组件中参数的变化做出响应的话,你可以简单地 watch 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) }, }
捕获所有路由或 404 Not found路由
常规参数只匹配 url 片段之间的字符, 用 / 分隔。 如果我们想匹配任意路径,我们可以使用自定义的 路径参数 正则表达式
const routes = [ // 将匹配所有内容并将其放在 `$route.params.pathMatch` 下 { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound }, // 将匹配以 `/user-` 开头的所有内容,并将其放在 `$route.params.afterUser` 下 { path: '/user-:afterUser(.*)', component: UserGeneric }, ]
在这个特定的场景中,我们在括号之间使用了自定义正则表达式,并将 pathMatch 参数标记位可选可重复。这样做时为了让我们在需要的时候,可以通过将 path 拆分成数组,直接导航到路由:
this.$router.push({ name: 'NotFound', params: { pathMatch: this.$route.path.split('/') }, })
大多数应用都会使用 /about 这样的静态路由和 /users/:userId 这样的动态路由。想象一下,两个路由 /:orderId 和 /:productName,两者会匹配完全相同的URL,所以我们需要一种方法来区分它们。
(1)、添加静态部分
const routes = [ // 匹配 /o/3549 { path: '/o/:orderId' }, // 匹配 /p/books { path: '/p/:productName' }, ]
(注:确保转义反斜杠(\)
(2)、在括号中为参数指定一个自定义的正则
const routes = [ // /:orderId -> 仅匹配数字 { path: '/:orderId(\\d+)' }, // /:productName -> 匹配其他任何内容 { path: '/:productName' }, ]
可重复的参数
如果你需要匹配具有多个部分的路由, 如 /first/second/third, 你应该用 * (0 个 或 多个) 和 + (1个或多个)将参数标记为可重复:
const routes = [ // /:chapters -> 匹配 /one, /one/two, /one/two/three, 等 { path: '/:chapters+' }, // /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等 { path: '/:chapters*' }, ]
// 给定 { path: '/:chapters*', name: 'chapters' }, router.resolve({ name: 'chapters', params: { chapters: [] } }).href // 产生 / router.resolve({ name: 'chapters', params: { chapters: ['a', 'b'] } }).href // 产生 /a/b // 给定 { path: '/:chapters+', name: 'chapters' }, router.resolve({ name: 'chapters', params: { chapters: [] } }).href // 抛出错误,因为 `chapters` 为空
const routes = [ // 仅匹配数字 // 匹配 /1, /1/2, 等 { path: '/:chapters(\\d+)+' }, // 匹配 /, /1, /1/2, 等 { path: '/:chapters(\\d+)*' }, ]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端