Vue3 路由基础
一个网站通常有”首页、列表、详情”等多个页面,传统网站里每个页面是一个独立的 HTML 文件,点开链接浏览器就整页刷新一次。
Vue 这类框架做的是 SPA(单页应用),整个站点只有一个 HTML 文件,切换页面只是替换页面组件,浏览器全程不刷新。
页面虽然没切换,但地址栏 URL 可是要跟着变的,不然浏览器的前进后退功能就会失效,也无法分享当前页面。
把”地址栏 URL”和”当前显示哪个组件”对应起来的机制,就是路由,它是 SPA 的地基,Vue 官方的路由方案是 Vue Router,当前主版本 4.x,完全贴合组合式 API。
安装
在项目根目录(有 package.json 和 src/main.js 的目录)执行:
npm install vue-router@4
配置路由
路由的配置写在独立文件里,新建 src/router/index.js,然后要做两件事,写一张路由表(地址 → 组件的对应关系),再基于它创建一个 router 实例。
路由表本身不会干活,需要一个对象把”匹配地址、执行跳转、管理历史”这些能力组装起来,这个对象就是 router 实例,由 createRouter 创建。
它接收一个配置对象,两个核心选项是 routes(路由表)和 history(URL 的显示形式):
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/HomeView.vue'
import About from '../views/AboutView.vue'
// 路由表:一条记录就是一个"地址 → 组件"的对应
const routes = [
{ path: '/', component: Home }, // 访问 / 显示 Home 组件
{ path: '/about', component: About } // 访问 /about 显示 About 组件
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
history 选项可以是 createWebHistory 或 createWebHashHistory。
createWebHashHistory:地址带#(/#/about),配置最简单,代价是 URL 不干净,一般用在无所谓SEO的场景。createWebHistory:最常用的方式,也是默认选择。
createWebHistory() // 部署在根目录
createWebHistory('/blog/') // 部署在子路径,例如 https://a.com/blog/
router 本质是一个 Vue 插件,要在 main.js 里交给应用使用:
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
渲染路由:router-view 与 router-link
路由表配好了,路由匹配到的组件要渲染到页面哪个位置?这由 <router-view> 决定。
它是页面上的一块占位区域,当前路由对应哪个组件,哪个组件就被填进这里.
提供”从哪跳”的是 <router-link>,它最终渲染成一个 <a> 标签,但比原生链接聪明,它接管点击,拦截掉整页刷新,只通知路由去换组件,还自动给当前处于激活状态的链接加上 router-link-active 类,配一段 CSS 就能实现导航高亮,它的 to 属性就是目标地址,字符串或对象都行:
<!-- App.vue -->
<template>
<nav>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
</nav>
<!-- 路由匹配到的组件渲染到这里 -->
<router-view />
</template>
打开首页看到首页组件,手动改成 /about 看到关于组件,中间没有任何刷新,这就是路由在干活。
切换路由时组件会重新创建吗
默认会,换一个路由,旧组件卸载、新组件挂载,行为跟动态组件一致。
直接感受是,切走再切回来,组件里的临时状态(比如填了一半的表单)会清空,这是正常行为。
想保留状态,Vue3 动态组件与缓存 里讲过的 KeepAlive 能解决,进阶篇也会再提到。
编程式导航
<router-link> 适合模板里的链接,但跳转不都从链接出发,按钮点击后跳转、登录成功跳首页、倒计时结束自动跳走,这些场景要在 JS 里主动跳转。
组合式 API 的思路是提供一个钩子函数,useRouter 就是这样的入口,在组件里调用就能拿到当前应用的 router 实例:
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const goAbout = () => {
router.push('/about') // 前进到 /about,历史栈记录
// router.replace('/about') // 替换当前记录,不留历史
// router.back() // 返回上一页
}
</script>
<template>
<button @click="goAbout">去关于页</button>
</template>
router 实例上常用的跳转方法有三个,看各自用途。
router.push(to)
router.push(to) 是”前进并留痕”,往历史栈里压入一条新记录,用户能按返回键回到当前页。
to 可以是字符串 '/about',也可以是对象 { path: '/about' },对象写法在进阶篇展开。
它返回一个 Promise,导航完成或失败时落定,多数场景不用管:
router.push('/about')
router.push({ path: '/about' })
router.replace(to)
router.replace(to) 是”覆盖当前记录”,不留退路。
有些页面不希望用户”退回去”,比如登录成功后按返回键不该回到登录页,适合登录、支付这类页面:
router.replace('/login') // 替换当前记录,返回键回不到这里
router.back()
router.back() 相当于浏览器返回键,由 router 提供,不依赖浏览器:
router.back()
获取当前路由
跳转之外,还常有”我现在在哪个地址”的需求,比如导航高亮当前菜单、详情页读取 URL 里的参数,useRoute 负责把当前匹配到的 route 对象交到组件手中。
route 对象记录当前地址的各种信息,常用属性有 path、name、params、query:
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>
path是当前路径,如/aboutname是当前路由的名字,Vue3 路由进阶 讲命名路由时展开params、query分别对应路径参数和查询参数,动态路由取参数时用到,进阶篇展开
速查卡片
| 场景 | 写法 |
|---|---|
| 安装 | npm install vue-router@4 |
| 定义路由 | createRouter({ history, routes }) + app.use(router) |
| 声明式跳转 | <router-link to="/about"> |
| 出口 | <router-view /> |
| JS 跳转 | useRouter() → router.push('/x') |
| 读取当前路由 | useRoute() |
| 刷新 404 | History 模式需服务器 fallback(或用 hash 模式) |