一、前言
上篇的 RouterLink 解决了"点链接跳转",但真实项目一半以上的跳转在代码里 :登录成功进首页、提交订单回列表、删除完刷新当前页。这就是编程式导航 。本篇讲透两对工具:声明式 RouterLink vs 编程式 router.push,以及读取路由信息的 useRoute------useRouter / useRoute 双子星是路由篇出场率最高的 API。
二、先分清:useRouter 和 useRoute 不是同一个东西
| useRouter | useRoute | |
|---|---|---|
| 拿到什么 | 路由器(能发起跳转) | 当前路由信息(只读) |
| 干什么 | push / replace / back | 读 params / query / path |
| 类比 | 遥控器 | 说明书 |
ts
import { useRouter, useRoute } from 'vue-router'
// 必须在 setup 顶层同步调用(028 篇 inject 的同款铁律)
const router = useRouter() // 用来"动"
const route = useRoute() // 用来"读"
新手第一坑预告:两者名字就差一个字母,route.push() 会报错------动用 router,读用 route。
三、声明式导航:RouterLink 详解
vue
<template>
<!-- 字符串路径 -->
<RouterLink to="/about">关于</RouterLink>
<!-- 对象写法:按 name 跳(045 篇推荐铁律) -->
<RouterLink :to="{ name: 'about' }">关于</RouterLink>
<!-- 带参数:路径参数 -->
<RouterLink :to="{ name: 'user', params: { id: 1 } }">用户1</RouterLink>
<!-- 带参数:query 查询串 -->
<RouterLink :to="{ name: 'search', query: { kw: 'vue' } }">搜索vue</RouterLink>
<!-- 替换历史记录(不留后退痕迹) -->
<RouterLink to="/about" replace>关于(replace)</RouterLink>
</template>
激活态样式:RouterLink 匹配当前 URL 时自动加两个 class:
vue
<style>
/* 模糊匹配:当前路由是 /about/team 时,/about 的链接也有它(常用于父级菜单高亮) */
.router-link-active { color: #42b983; }
/* 精确匹配:完全一致才加(当前页面链接) */
.router-link-exact-active { font-weight: bold; }
</style>
想换 class 名用 active-class / exact-active-class 属性,后台菜单高亮全靠这套(068 篇会实战)。
四、编程式导航:router.push 全家桶
vue
<template>
<button @click="goAbout">跳到关于</button>
<button @click="goUser">跳到用户1</button>
<button @click="goSearch">带查询参数跳转</button>
<button @click="replaceHome">替换成首页(无后退痕迹)</button>
<button @click="goBack">后退</button>
<button @click="goForward">前进</button>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
const router = useRouter()
// push:追加一条历史记录(最常用)
function goAbout() {
router.push('/about') // 字符串路径
}
function goUser() {
router.push({ name: 'user', params: { id: 1 } }) // 按名 + 路径参数
}
function goSearch() {
router.push({ name: 'search', query: { kw: 'vue3' } }) // query 会变成 ?kw=vue3
}
// replace:替换当前记录------登录页跳首页常用,防止后退回登录页
function replaceHome() {
router.replace('/')
}
// 历史 API
function goBack() {
router.back() // 等价 router.go(-1)
}
function goForward() {
router.forward() // 等价 router.go(1)
}
</script>
四个方法记忆:push(追加)、replace(替换)、back/forward(历史)。跳转是异步的(返回 Promise),需要"跳转完成后做事"可以 await。
五、useRoute:读取当前路由的一切
vue
<template>
<p>路径:{{ route.path }}</p>
<p>完整路径:{{ route.fullPath }}</p>
<p>路由名:{{ route.name }}</p>
<p>查询参数:{{ route.query }}</p>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router'
const route = useRoute()
// route 是响应式的:URL 一变,这些值自动更新,模板跟着重渲染
</script>
route 对象常用字段:path (路径)、fullPath (路径+查询串)、name 、params (路径参数,047 篇主角)、query (查询参数)、hash 、meta(050 篇主角)。
六、综合实战:迷你导航站
把本篇 API 全部串起来(路由配置沿用 045 + 临时加一条 search):
ts
// src/router/index.ts 里补一条(search 页面随便建一个)
{ path: '/search', name: 'search', component: () => import('@/views/SearchView.vue') }
vue
<!-- src/views/SearchView.vue:读取 query 并展示 -->
<template>
<h2>🔍 搜索页</h2>
<p>你搜索的关键词是:{{ route.query.kw ?? '(无)' }}</p>
<input v-model="kw" placeholder="换个关键词再搜" />
<button @click="research">重新搜索</button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
const kw = ref('')
// 用新 query 替换当前路由(URL 变、历史也变)
function research() {
router.push({ name: 'search', query: { kw: kw.value } })
}
</script>
vue
<!-- src/App.vue:导航站主页 -->
<template>
<nav>
<RouterLink to="/">首页</RouterLink>
<RouterLink to="/about">关于</RouterLink>
<RouterLink :to="{ name: 'search', query: { kw: 'vue3' } }">搜 Vue3</RouterLink>
</nav>
<RouterView />
<hr />
<button @click="router.back()">← 后退</button>
<button @click="router.forward()">前进 →</button>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
const router = useRouter()
</script>
玩一遍:链接跳转看 URL 变化 → 搜索页改关键词"重新搜索"看 query 更新 → 后退前进体会历史栈 → 注意搜索页组件没有重建 ,但 route.query 的展示变了(route 是响应式的,这是 047 篇"参数变化监听"的伏笔)。
【截图位置:搜索页 query 变化、后退前进操作的运行效果】
七、踩坑记录
- router 和 route 用混 :
route.push()报错(route 是只读信息)------动 router、读 route - 在 setup 外/异步回调里调用 useRouter :
setTimeout(() => { const r = useRouter() })拿不到------先在 setup 顶层接住const router = useRouter()再到处用 - params 丢了 :
router.push({ name: 'user', params: { id: 1 } })但路由表里没配/user/:id,params 会被丢弃------先确认 047 篇的动态路由配了 - 用 path 跳转却带 params :
router.push({ path: '/user', params: { id: 1 } })params 无效------path 配 query,name 配 params(这是官方规则) - 模板里少写冒号 :
<RouterLink to="{ name: 'about' }">传的是字符串------对象写法必须:to - replace 和 push 傻傻分不清 :登录成功后如果用 push,用户后退会回到登录页(已登录状态不该回去)------身份切换类跳转用 replace
八、今日小结
- 双子星:useRouter 发起跳转(push/replace/back) ,useRoute 只读当前路由信息
- 声明式 RouterLink 管导航链接,激活 class(router-link-active 等)免费送
- 跳转铁律:name 配 params,path 配 query;身份切换用 replace
- route 是响应式的------URL 变,读到的值自动更新
下篇预告
URL 里传数据是路由的核心能力:详情页的 /user/1、列表页的搜索条件。下一篇 047 动态路由与路由参数------:id 传参、query 传参、props 解耦,以及"同一页面参数变了却不刷新"的经典坑。