动态路由
如果有很多遵循相同格式的数据,例如用户列表或消息列表,并且需要为每个数据创建一个页面,我们需要使用路由模式。 通过路由模式,我们可以根据一些附加信息从同一组件动态创建新路由。 例如,我们希望为每个用户呈现用户视图组件,但具有不同的 id 值。 Vue Router 为我们提供了使用冒号(:)表示的动态段来实现动态路由的能力。
我们不使用在刷新时保留其值或出现在 URL 中的参数(params),而是直接在路径中定义所需的参数,如下所示:
{
path: '/user/:id',
name: 'user',
component: () => import(/* webpackChunkName: "user" */ '../views/User.vue')
}
在上面的代码中,:id 表示这里的参数不是静态的。 当路由与给定模式匹配时,Vue Router 将使用适当的内容渲染相应的组件,同时保持 URL 应有的样子。 并且 :id 的值将在该视图组件的实例中公开为 $route.params.id
:
<template>
<div>
<h1>About a user: {{$route.params.id}}</h1>
</div>
</template>
当用户选择 /user/1 和 /user/2 (./src/App.vue) 等 URL 时,Vue 将使用我们的模板自动生成子页面。
导航路径将映射到相同的路由模式和组件,但具有不同的信息,如以下屏幕截图所示:

当您单击用户 1 时,您将看到以下内容:

我们还可以使用 props: true
将 id 规范化为 User 组件的 props,并将其与 beforeRouteEnter() 结合起来,以在创建和渲染实例之前加载所选用户的数据:
<script>
import users from '../assets/users.js';
export default {
props: {
id: Number
},
data() {
return {
name: '',
age: 0
}
},
beforeRouteEnter(to, from, next) {
next(vm => {
const user = users[vm.id];
vm.name = user.name;
vm.age = user.age;
})
}
}
</script>
现在我们可以调整 <template> 来打印用户的详细信息:
<template>
<div>
<h1>About a user: {{$route.params.id}}</h1>
<h2>Name: {{name}}</h2>
<p>Age: {{age}}</p>
</div>
</template>
选择 /user/1 时的输出现在如下:

如果我们在 user/:id
路由中并将 :id
更改为另一个用户,我们需要相应地更新本地数据,因为在这种情况下 beforeRouteEnter
不会再次被触发。事实上,组件的所有生命周期 Hook 都不会被调用,因为组件实例没有被重新创建:
beforeRouteUpdate(to, from, next) {
const user = users[to.params.id - 1];
this.name = user.name;
this.age = user.age;
next();
}
在本节中,我们通过设置从给定 URL 中提取参数的路由来了解动态路由。该技术允许您创建用户友好的 URL 并将信息动态传递给路由。在下一节中,我们将研究捕获错误路径。
捕获错误路径
除了主页(“/”)之外,我们始终需要记住处理的其它重要路由包括错误路由,例如当 URL 路径与任何注册路径不匹配时出现 404 Not found 等。
对于 404 Not found,我们可以使用正则表达式星号 *
,它代表匹配所有内容来收集所有与路由不匹配的情况。 该路由器的配置应位于数组路由的末尾,以避免匹配错误的路径:
{
path: '*',
name: '404',
component: () => import(/* webpackChunkName: "404" */ '../views/404.vue'),
}
当我们输入错误的 /users 路径时,输出将如下:

在本节中,我们了解了如何使用 *
正则表达式通配符创建一个包罗万象的 404 页面,向导航到不存在的路由的任何人显示。 接下来,我们将实现一个消息路由,使用动态路由模式在 URL 本身中传递相关数据。
练习 6.05:使用动态路由模式为每条消息实现消息路由
回到练习 6.04 中的消息源,将消息列表提取到外部文件并仅在查看 MessageFeed 时加载,我们将重构消息路径,以使用路由模式根据用户的选择动态导航到特定消息路径。 这将使您熟悉与其它导航 Hook 结合创建和维护动态路由。
要访问本练习的代码文件,请参阅 https://packt.live/32sWogX 。
-
让我们打开 ./src/router/index.js 并将消息路由的路径配置更改为
/message/:id
,其中 id 将是该消息在消息列表中的索引:{ path: '/message/:id', name: 'message', component: () => import(/* webpackChunkName: "message" */'../views/Message.vue'), props: true, }
-
现在导航到 ./src/views/MessageFeed.vue 并将每条消息的 router-link 的 to 属性更改为以下内容:
<router-link :to="`/message/${i}`">
-
让我们回到 ./src/router/index.js 并将 beforeEnter 定义为异步 Hook,用于将消息内容延迟加载到 Message 组件的 content 属性中:
async beforeEnter(to, from, next) { if (to.params && to.params.id) { const id = to.params.id; const { module } = await import (/* webpackChunkName: "messagesFeed" */ '../assets/messages.js'); const messages = module.default; if (messages && messages.length > 0 && id < messages.length) { to.params.content = messages[id]; } } next() },
-
使用以下命令运行应用程序:
yarn serve
当点击消息源中的第一条消息时,下一页将如下所示:
Figure 5. Figure 6.36: The page displayed when visiting the /message/0 path
现在您已经了解了如何使用动态路由,您可以进一步尝试更多层的路由模式,例如 message/:id/author/:aid
。然而,对于这种情况,我们通常使用更好的方法,即嵌套路由。