02|RouterView 与 RouterLink
第六章概览 / 02。目标:route record 只决定“匹配谁”,
RouterView决定“渲染在哪”,RouterLink提供可复制、可键盘操作的导航入口。
应用壳的最小组件
<!-- App.vue -->
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
</script>
<template>
<header>
<nav aria-label="主导航">
<RouterLink to="/">首页</RouterLink>
<RouterLink :to="{ name: 'user', params: { id: '42' } }">用户 42</RouterLink>
</nav>
</header>
<main>
<RouterView />
</main>
</template>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RouterLink 最终渲染可访问的 <a href>,Vue Router 拦截符合条件的同源点击并执行客户端导航;新标签打开、复制链接和键盘激活仍保留浏览器语义。不要用 <div @click="router.push(...)" /> 伪造普通链接。
RouterView 根据当前位置的 matched records 和自身深度选择组件。顶层 view 渲染第一层记录;父页面内部的下一层 view 渲染 child record。
激活状态不是手写路径前缀
默认 class 是:
router-link-active:目标 route record 和参数匹配,祖先链接也可能激活。router-link-exact-active:当前位置正好匹配目标。
RouterLink 会为精确激活的链接设置 aria-current="page"(可用 aria-current-value 调整)。全局可在 createRouter 配置 linkActiveClass/linkExactActiveClass,或按组件传 active-class。
custom slot 保留导航合同
<RouterLink
v-slot="{ href, navigate, isActive, isExactActive }"
custom
:to="{ name: 'user', params: { id: '42' } }"
>
<a
:href="href"
:aria-current="isExactActive ? 'page' : undefined"
:class="{ active: isActive }"
@click="navigate"
>
打开用户
</a>
</RouterLink>2
3
4
5
6
7
8
9
10
11
12
13
14
navigate 负责识别修饰键、目标窗口等链接行为;只调用 router.push 会丢掉一部分原生语义。若只是改样式,优先使用默认 RouterLink,不必 custom。
RouterView slot 包裹的是路由组件
<RouterView v-slot="{ Component, route }">
<Transition name="fade" mode="out-in">
<component :is="Component" :key="route.name ?? route.path" />
</Transition>
</RouterView>2
3
4
5
Router 4 中把 Transition/KeepAlive 放在 RouterView slot 内,才能包住真正的路由组件。route 也可用于 key,但不要习惯性使用 route.fullPath:query/hash 每变一次都会销毁并重建页面,局部状态和请求随之重置。只有“位置变化必须新建实例”时才选择相应 key。
缓存页面时:
<RouterView v-slot="{ Component }">
<KeepAlive :max="5">
<component :is="Component" />
</KeepAlive>
</RouterView>2
3
4
5
被 KeepAlive 停用的组件没有卸载。需要暂停计时器或重新验证数据时,使用 onDeactivated/onActivated,并设置 max/include/exclude 控制缓存;Router 没有通用 API 按路由手动删除某个 KeepAlive 缓存。
失败路径
- route 已匹配但页面空白:父级布局缺少对应深度的
<RouterView>。 - custom link 只渲染按钮:链接不可复制/新标签打开。普通页面跳转仍应使用
<a>。 - 用
fullPath做 key:改一个筛选 query 就丢失整页实例。 - 把 route component 写在 RouterView 外层 Transition:过渡对象变成 RouterView 本身,效果和生命周期不符合预期。
- 只看颜色判断激活:还要验证 focus、键盘和
aria-current。
练习:可访问的后台导航
创建 /settings/profile 与 /settings/security 两个链接和一个 <RouterView>。要求:父级 /settings 链接在两个子页都 active,当前子页 exact-active;支持键盘和新标签打开;用 custom slot 加一个角标但仍渲染 <a>。
本题的父子 record 配置先读嵌套路由与布局,再回访完成父链接激活的部分;当前先实现两个可访问链接与 custom slot。
变化题:将路由组件包进 KeepAlive,证明切换子页后表单草稿保留;再写出在登出时不能依赖 KeepAlive 自动清理的原因。
参考答案:第 02 题。
本页结论
route records 描述组件树,RouterView 提供出口,RouterLink 提供浏览器级导航入口。样式定制不能破坏链接语义,缓存/重建必须是显式生命周期决策。