路由基础与动态参数
Vue Router 4 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。
学习目标
Vue Router 是 Vue 官方路由。这一节掌握路由表配置、<RouterLink> 与 <RouterView> 的职责、动态参数的读写,以及页面标题、滚动行为这些经常被忽略的细节。
问题场景
一个三页小站:首页、课程列表、课程详情。用 v-if 切换页面能跑,但刷新后退回首页、无法分享链接、浏览器前进后退失效。换成 Vue Router 后,新问题又来了:详情页 /courses/v01 里 id 怎么拿?从列表点进详情再点另一门课,URL 变了但页面没更新(组件被复用)?
核心解释
先建路由表。createRouter + createWebHistory(或 createWebHashHistory),每条路由映射一个组件:
路由表的最小形态是 createRouter({ history: createWebHistory(), routes: [...] }):每条路由写成 { path, name, component },:slug 是路径参数,兜底路由用 /:pathMatch(.*)*。scrollBehavior 管滚动位置,router.afterEach 适合统一设置页面标题。完整的路由表在下面的示例拆解里。
main.js 里 app.use(router),App.vue 里放 <RouterView /> 作为出口、<RouterLink to="/courses"> 做导航。
动态参数::slug 是路径参数。组件里用 useRoute() 拿当前路由(响应式对象),用 useRouter() 拿路由器实例(方法集合):
<script setup>
import { computed, watch } from "vue";
import { useRoute } from "vue-router";
const route = useRoute();
const slug = computed(() => route.params.slug);
// 同一路由不同参数切换时组件会被复用,需要侦听参数变化
watch(
() => route.params.slug,
(value) => {
console.log("切换到课程", value);
}
);
</script>
<template>
<p>当前课程:{{ slug }}</p>
</template>
这是 Vue Router 和 React Router 都存在的经典坑:从 /courses/a 跳到 /courses/b,路由匹配到同一个组件,组件不会销毁重建,所以「在 setup 里读一次 params」拿到的还是旧值。解法三种:侦听 params(如上)、给 <RouterView> 加 :key="route.fullPath" 强制重建、或用 beforeRouteUpdate(Options API)。
props: true 让路径参数直接作为组件 props 传入,组件不再依赖路由上下文,可测试性更好。组件里这样声明:
示例拆解
一个带 404 与标题的三页小站骨架:
// router/index.js(完整)
import { createRouter, createWebHistory } from "vue-router";
export const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/", name: "home", component: () => import("../views/HomeView.vue"), meta: { title: "首页" } },
{
path: "/courses",
name: "courses",
component: () => import("../views/CoursesView.vue"),
meta: { title: "课程" },
},
{
path: "/courses/:slug",
name: "course",
component: () => import("../views/CourseView.vue"),
props: true,
meta: { title: "课程详情" },
},
{
path: "/:pathMatch(.*)*",
name: "not-found",
component: () => import("../views/NotFound.vue"),
meta: { title: "页面不存在" },
},
],
});
<!-- App.vue -->
<script setup>
import { RouterLink, RouterView } from "vue-router";
</script>
<template>
<nav>
<RouterLink to="/">首页</RouterLink>
<RouterLink to="/courses">课程</RouterLink>
</nav>
<main>
<RouterView />
</main>
</template>
<RouterLink> 会渲染成 <a> 并自动处理「当前激活」样式(router-link-active)。/:pathMatch(.*)* 是官方的兜底写法,匹配所有未命中的路径。
动手任务
- 建一个三页小站(首页/列表/详情),验证浏览器前进后退、刷新详情页、直接输入 URL 三种行为都正确。
- 给详情页加「上一课/下一课」按钮,用
router.push({ name: "course", params: { slug: next } })实现。 - 复现「同路由不同参数不更新」的 bug,再用
watch(route.params.slug)修复,记录两种解法。
常见错误
- 用
useRoute()拿 router 实例:useRoute返回当前路由信息(params/query/path),导航方法在useRouter()上。 - 在 setup 里一次性读
route.params:同组件参数变化时不会更新。用 computed 或 watch。 - 以为
<RouterLink>会整页刷新:它是客户端导航;需要整页刷新时用普通<a>。 - 路由表漏了 404 兜底:访问不存在的路径显示空白。
检查与复盘
- 能写出含动态参数、404 兜底、懒加载的路由表
- 能解释
useRoute与useRouter的分工 - 能说出「同路由参数变化组件复用」的三种解法
参考资料
- Vue Router 官方文档「入门」:安装与基础配置
- Vue Router 官方文档「动态路由匹配」:参数与复用问题
读完这一课了?
标记完成后,工作台会安排接下来的学习。