package.json 中的 vue-router 详解
vue-router 是 Vue 官方提供的前端路由库,主要用于 Vue 单页应用中不同页面之间的切换。
例如:
bash
/login 登录页
/home 首页
/user 用户列表
/user/1001 用户详情
这些地址对应不同的 Vue 组件,但切换时通常不会重新加载整个网页。
1. package.json 中的 vue-router
通常会看到:
json
{
"dependencies": {
"vue": "^3.5.0",
"vue-router": "^4.5.0"
}
}
这里:
json
"vue-router": "^4.5.0"
各部分含义如下:
vue-router:依赖包名称。4.5.0:安装的版本范围基准。^:允许安装兼容的较新版本。
版本号一般由三部分组成:
4.5.0
│ │ │
│ │ └─ 补丁版本 patch
│ └─── 次版本 minor
└───── 主版本 major
^4.5.0 一般允许升级到:
shell
>= 4.5.0,并且 < 5.0.0
例如可能安装:
4.5.1
4.6.0
4.9.0
但不会自动升级到:
5.0.0
Vue 3 对应的是 Vue Router 4:
Vue 2 → vue-router 3
Vue 3 → vue-router 4
2. 为什么放在 dependencies 中?
dependencies 存放项目运行时需要的依赖:
json
{
"dependencies": {
"vue": "^3.5.0",
"vue-router": "^4.5.0",
"axios": "^1.11.0"
}
}
项目运行时,需要 vue-router 完成页面路由切换,所以它通常放在 dependencies 中。
而下面这些构建工具一般放在 devDependencies:
json
{
"devDependencies": {
"typescript": "^5.8.0",
"vite": "^7.0.0",
"eslint": "^9.0.0"
}
}
简单理解:
dependencies:程序运行需要。devDependencies:开发、检查、编译时需要。
3. 安装 Vue Router
使用 npm:
npm install vue-router
使用 pnpm:
csharp
pnpm add vue-router
指定 Vue Router 4:
css
npm install vue-router@4
安装后,package.json 中会自动出现:
json
{
"dependencies": {
"vue-router": "^4.5.0"
}
}
同时依赖代码会被下载到:
bash
node_modules/vue-router
锁文件中也会记录准确版本:
csharp
package-lock.json
pnpm-lock.yaml
yarn.lock
不要只手动修改 package.json 而不执行安装,否则 node_modules 中可能没有这个包。
Vue Router 的基本配置
4. 创建页面组件
假设项目结构如下:
css
src/
├─ views/
│ ├─ Home.vue
│ ├─ Login.vue
│ └─ User.vue
├─ router/
│ └─ index.ts
├─ App.vue
└─ main.ts
Home.vue:
xml
<template>
<div>首页</div>
</template>
Login.vue:
xml
<template>
<div>登录页</div>
</template>
5. 创建路由配置
在 src/router/index.ts 中:
javascript
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue'),
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
},
]
const router = createRouter({
history: createWebHistory(),
routes,
})
export default router
这里主要做了三件事:
- 定义地址和页面组件的对应关系。
- 创建路由实例。
- 导出路由实例。
6. createRouter
css
const router = createRouter({
history: createWebHistory(),
routes,
})
createRouter() 用于创建路由对象。
它接收一个配置对象:
yaml
{
history: 路由模式,
routes: 路由规则数组
}
创建完成后,router 负责:
- 监听浏览器地址变化。
- 根据地址找到对应组件。
- 控制页面组件切换。
- 管理前进、后退。
- 执行路由守卫。
7. routes 路由表
javascript
const routes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
},
]
每个对象就是一条路由规则。
path
lua
path: '/login'
表示浏览器地址:
bash
http://localhost:5173/login
访问 /login 时,显示该路由对应的组件。
name
vbnet
name: 'Login'
表示路由名称。
可以通过名称跳转:
css
router.push({
name: 'Login',
})
建议每条重要路由的 name 保持唯一。
component
javascript
component: () => import('@/views/Login.vue')
表示访问该路由时加载哪个 Vue 组件。
这种写法叫动态导入或懒加载:用户访问这个页面时才加载对应文件,有利于减少首页资源体积。
也可以直接导入:
javascript
import Login from '@/views/Login.vue'
const routes = [
{
path: '/login',
component: Login,
},
]
直接导入通常会把页面组件放进初始资源中。实际项目的页面路由通常更常使用懒加载。
在 Vue 应用中注册路由
8. 修改 main.ts
javascript
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
最关键的是:
php
app.use(router)
它把路由插件安装到整个 Vue 应用中。
注册后,组件中才能使用:
<RouterView><RouterLink>useRouter()useRoute()
一般要在:
arduino
app.mount('#app')
之前注册。
显示路由页面
9. RouterView
在 App.vue 中:
xml
<template>
<RouterView />
</template>
<RouterView /> 是路由页面的显示位置,可以理解为一个页面出口。
如果当前地址是:
bash
/login
RouterView 会显示:
Login.vue
如果当前地址是:
/
它会显示:
Home.vue
如果没有写 <RouterView />,浏览器地址可能改变了,但对应页面组件没有地方显示。
10. RouterLink
声明式路由跳转可以使用:
xml
<template>
<RouterLink to="/">
首页
</RouterLink>
<RouterLink to="/login">
登录页
</RouterLink>
<RouterView />
</template>
它最终通常会生成类似 <a> 的元素,但由 Vue Router 控制跳转,不会像普通链接一样重新加载整个页面。
根据路由名称跳转:
ini
<RouterLink :to="{ name: 'Login' }">
登录页
</RouterLink>
在代码中跳转页面
11. useRouter
useRouter() 获取整个路由实例,主要用于执行跳转。
xml
<script lang="ts" setup>
import { useRouter } from 'vue-router'
const router = useRouter()
function goLogin() {
router.push('/login')
}
</script>
<template>
<button @click="goLogin">
去登录页
</button>
</template>
根据路由名称跳转:
css
router.push({
name: 'Login',
})
返回上一页:
scss
router.back()
前进:
scss
router.forward()
前进或后退指定层数:
go
router.go(-1)
router.go(1)
12. push 和 replace 的区别
router.push
arduino
router.push('/home')
会在浏览器历史记录中增加一条记录。
例如:
登录页 → 首页
在首页点击浏览器后退,可以回到登录页。
router.replace
arduino
router.replace('/home')
会替换当前历史记录。
例如登录成功后:
arduino
router.replace('/home')
用户点击后退时,通常不会再次回到登录页面。
简单理解:
push:新增历史记录。replace:替换当前历史记录。
获取当前路由信息
13. useRoute
useRoute() 用于获取当前页面的路由信息:
xml
<script lang="ts" setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.path)
console.log(route.name)
console.log(route.params)
console.log(route.query)
</script>
注意区别:
ini
const router = useRouter()
const route = useRoute()
router:负责跳转和控制路由。route:保存当前路由的信息。
可以记成:
router:路由控制器
route:当前路由数据
路由参数
14. 动态参数 params
路由配置:
css
{
path: '/user/:id',
name: 'UserDetail',
component: () => import('@/views/UserDetail.vue'),
}
这里:
bash
:id
表示动态参数。
访问:
bash
/user/1001
其中 1001 就是 id。
组件中获取:
javascript
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params.id) // 1001
跳转:
php
router.push({
name: 'UserDetail',
params: {
id: 1001,
},
})
结果地址:
bash
/user/1001
通过 params 跳转时,推荐使用路由名称 name。
15. 查询参数 query
跳转:
php
router.push({
path: '/user',
query: {
page: 1,
keyword: 'camera',
},
})
最终地址:
ini
/user?page=1&keyword=camera
获取参数:
scss
const route = useRoute()
console.log(route.query.page)
console.log(route.query.keyword)
params 和 query 的区别
params:
bash
/user/1001
获取:
csharp
route.params.id
query:
bash
/user?id=1001
获取:
python
route.query.id
一般来说:
- 用户、文章详情 ID:常用
params。 - 搜索、分页、筛选条件:常用
query。
嵌套路由
16. children
例如用户中心包含个人信息和设置:
javascript
const routes = [
{
path: '/user',
component: () => import('@/views/UserLayout.vue'),
children: [
{
path: 'profile',
component: () => import('@/views/UserProfile.vue'),
},
{
path: 'settings',
component: () => import('@/views/UserSettings.vue'),
},
],
},
]
访问地址:
bash
/user/profile
/user/settings
父组件 UserLayout.vue 必须提供子路由出口:
xml
<template>
<div>
<h2>用户中心</h2>
<RouterView />
</div>
</template>
注意子路由通常写成:
lua
path: 'profile'
而不是:
lua
path: '/profile'
不带 / 表示它相对于父路由 /user。
路由重定向与 404
17. redirect
访问一个地址后自动跳转到另一个地址:
css
{
path: '/',
redirect: '/home',
}
也可以按照名称:
css
{
path: '/',
redirect: {
name: 'Home',
},
}
18. 404 路由
css
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('@/views/NotFound.vue'),
}
这条路由表示匹配前面路由都没有匹配到的地址。
通常放在路由数组最后:
javascript
const routes = [
// 正常页面路由
{
path: '/:pathMatch(.*)*',
component: () => import('@/views/NotFound.vue'),
},
]
路由元信息
19. meta
可以给路由添加额外信息:
css
{
path: '/admin',
name: 'Admin',
component: () => import('@/views/Admin.vue'),
meta: {
title: '后台管理',
requiresAuth: true,
},
}
读取:
scss
const route = useRoute()
console.log(route.meta.title)
console.log(route.meta.requiresAuth)
常见用途:
- 页面标题。
- 是否需要登录。
- 用户权限。
- 菜单图标。
- 是否显示侧边栏。
- 页面缓存设置。
路由守卫
20. beforeEach
全局前置守卫在每次路由跳转前执行:
javascript
router.beforeEach((to, from) => {
console.log('准备进入:', to.path)
console.log('从哪里来:', from.path)
})
参数含义:
to:准备进入的路由。from:当前准备离开的路由。
登录验证示例:
javascript
router.beforeEach((to) => {
const token = localStorage.getItem('token')
if (to.meta.requiresAuth && !token) {
return {
name: 'Login',
}
}
})
含义是:
目标页面需要登录
并且当前没有 token
→ 跳转到登录页
允许继续进入时,可以不返回内容:
javascript
router.beforeEach(() => {
// 不返回,继续跳转
})
现在更推荐直接返回跳转位置,不必使用旧式的 next()。
21. 修改浏览器标题
结合 meta:
javascript
router.afterEach((to) => {
document.title = String(to.meta.title ?? '管理系统')
})
路由:
css
{
path: '/home',
meta: {
title: '首页',
},
}
访问首页后,浏览器标签标题会变成"首页"。
路由模式
22. createWebHistory
bash
history: createWebHistory()
地址比较正常:
arduino
https://example.com/home
https://example.com/user
优点是地址美观。
但部署到服务器时,需要服务器支持:当用户直接访问 /user 时,服务器应该返回项目的 index.html,交给 Vue Router 处理。
否则刷新页面可能出现 404。
23. createWebHashHistory
javascript
import {
createRouter,
createWebHashHistory,
} from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
routes,
})
地址带有 #:
bash
https://example.com/#/home
https://example.com/#/user
优点:
- 服务器通常不需要额外配置。
- 刷新页面不容易出现 404。
缺点:
- 地址中有
#,不如 history 模式美观。
简单选择:
- 正常 Web 项目并且服务器可以配置:
createWebHistory()。 - 无法配置服务器或简单静态部署:可以考虑
createWebHashHistory()。
常见完整配置
javascript
import {
createRouter,
createWebHistory,
} from 'vue-router'
const routes = [
{
path: '/',
redirect: '/home',
},
{
path: '/home',
name: 'Home',
component: () => import('@/views/Home.vue'),
meta: {
title: '首页',
requiresAuth: true,
},
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
meta: {
title: '登录',
requiresAuth: false,
},
},
{
path: '/user/:id',
name: 'UserDetail',
component: () => import('@/views/UserDetail.vue'),
meta: {
title: '用户详情',
requiresAuth: true,
},
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('@/views/NotFound.vue'),
},
]
const router = createRouter({
history: createWebHistory(),
routes,
})
router.beforeEach((to) => {
const token = localStorage.getItem('token')
if (to.meta.requiresAuth && !token) {
return {
name: 'Login',
query: {
redirect: to.fullPath,
},
}
}
})
router.afterEach((to) => {
document.title = String(to.meta.title ?? '管理系统')
})
export default router
main.ts:
javascript
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App)
.use(router)
.mount('#app')
App.vue:
xml
<template>
<RouterView />
</template>
初学者重点记忆
csharp
vue-router:Vue官方路由库
routes:地址和页面组件的对应关系
createRouter:创建路由实例
createWebHistory:选择路由模式
app.use(router):把路由注册到Vue应用
RouterView:显示当前路由对应的组件
RouterLink:声明式跳转
useRouter:执行路由跳转
useRoute:获取当前路由信息
params:路径参数
query:查询参数
children:嵌套路由
meta:路由附加信息
beforeEach:跳转前执行权限检查
最容易混淆的是:
scss
const router = useRouter() // 用来跳转
const route = useRoute() // 用来读取当前路由
例如:
scss
const router = useRouter()
const route = useRoute()
console.log(route.params.id)
router.push('/home')