351 lines
8.3 KiB
Markdown
351 lines
8.3 KiB
Markdown
# Vue Router 路由刷新问题修复
|
||
|
||
## 问题描述
|
||
用户反馈:**登录后跳转到 `http://localhost:8080/system/post`,刷新页面后路由变成 `http://localhost:8080/post`,导致页面空白**。
|
||
|
||
## 问题根源
|
||
|
||
### Vue Router 嵌套路由的路径规则
|
||
|
||
在 Vue Router 中,**子路由的 `path` 配置方式**决定了最终的 URL:
|
||
|
||
#### ❌ 错误配置(使用绝对路径)
|
||
```javascript
|
||
{
|
||
path: '/system',
|
||
component: LayoutIndex,
|
||
children: [
|
||
{
|
||
path: '/system/post', // ❌ 以 / 开头 = 绝对路径
|
||
component: () => import('~/views/system/post.vue'),
|
||
},
|
||
],
|
||
}
|
||
```
|
||
|
||
**问题**:
|
||
- 子路由使用 `/system/post`(以 `/` 开头)
|
||
- Vue Router 会将其视为**根路径**
|
||
- 刷新时路由解析错误,变成 `/post`
|
||
|
||
#### ✅ 正确配置(使用相对路径)
|
||
```javascript
|
||
{
|
||
path: '/system',
|
||
component: LayoutIndex,
|
||
children: [
|
||
{
|
||
path: 'post', // ✅ 不以 / 开头 = 相对路径
|
||
component: () => import('~/views/system/post.vue'),
|
||
},
|
||
],
|
||
}
|
||
```
|
||
|
||
**正确行为**:
|
||
- 子路由使用 `post`(不以 `/` 开头)
|
||
- Vue Router 会自动拼接:`/system` + `post` = `/system/post`
|
||
- 刷新时路由正常工作
|
||
|
||
## 修复内容
|
||
|
||
### 修复的路由模块
|
||
|
||
修复了以下所有嵌套路由的子路径配置:
|
||
|
||
1. **入境检疫** (`/entry`)
|
||
- `/entry/details` → `details`
|
||
- `/entry/devices` → `devices`
|
||
|
||
2. **系统管理** (`/system`)
|
||
- `/system/post` → `post`
|
||
- `/system/staff` → `staff`
|
||
- `/system/tenant` → `tenant`
|
||
|
||
3. **权限管理** (`/permission`)
|
||
- `/permission/menu` → `menu`
|
||
- `/permission/operation` → `operation`
|
||
|
||
4. **智能硬件** (`/hardware`)
|
||
- `/hardware/collar` → `collar`
|
||
- `/hardware/eartag` → `eartag`
|
||
- `/hardware/host` → `host`
|
||
|
||
5. **用户管理** (`/userManage`)
|
||
- `/userManage/user` → `user`
|
||
- `/userManage/driver` → `driver`
|
||
- `/userManage/vehicle` → `vehicle`
|
||
|
||
6. **早期预警** (`/earlywarning`)
|
||
- `/earlywarning/earlywarninglist` → `earlywarninglist`
|
||
|
||
7. **运送清单** (`/shipping`)
|
||
- `/shipping/loadingOrder` → `loadingOrder`
|
||
- `/shipping/shippinglist` → `shippinglist`
|
||
|
||
### 修复示例
|
||
|
||
**修复前**:
|
||
```javascript
|
||
{
|
||
path: '/system',
|
||
component: LayoutIndex,
|
||
children: [
|
||
{
|
||
path: '/system/post', // ❌ 绝对路径
|
||
name: 'Post',
|
||
component: () => import('~/views/system/post.vue'),
|
||
},
|
||
],
|
||
}
|
||
```
|
||
|
||
**修复后**:
|
||
```javascript
|
||
{
|
||
path: '/system',
|
||
component: LayoutIndex,
|
||
children: [
|
||
{
|
||
path: 'post', // ✅ 相对路径
|
||
name: 'Post',
|
||
component: () => import('~/views/system/post.vue'),
|
||
},
|
||
],
|
||
}
|
||
```
|
||
|
||
## Vue Router 路径规则详解
|
||
|
||
### 1. 绝对路径(以 `/` 开头)
|
||
|
||
```javascript
|
||
{
|
||
path: '/parent',
|
||
children: [
|
||
{ path: '/child' } // ❌ 结果:/child
|
||
]
|
||
}
|
||
```
|
||
|
||
- **行为**:忽略父路由路径,直接作为根路径
|
||
- **最终 URL**:`/child`
|
||
- **用途**:极少使用,仅当子路由确实需要在根路径下时
|
||
|
||
### 2. 相对路径(不以 `/` 开头)
|
||
|
||
```javascript
|
||
{
|
||
path: '/parent',
|
||
children: [
|
||
{ path: 'child' } // ✅ 结果:/parent/child
|
||
]
|
||
}
|
||
```
|
||
|
||
- **行为**:自动拼接父路由路径
|
||
- **最终 URL**:`/parent/child`
|
||
- **用途**:**推荐使用**,适用于绝大多数嵌套路由场景
|
||
|
||
### 3. 空路径
|
||
|
||
```javascript
|
||
{
|
||
path: '/parent',
|
||
children: [
|
||
{ path: '' } // 结果:/parent
|
||
]
|
||
}
|
||
```
|
||
|
||
- **行为**:匹配父路由路径本身
|
||
- **最终 URL**:`/parent`
|
||
- **用途**:默认子路由、索引页
|
||
|
||
## 为什么刷新会导致路由变化?
|
||
|
||
### 问题原因
|
||
|
||
1. **首次导航**(通过 `router.push`):
|
||
```javascript
|
||
router.push('/system/post')
|
||
```
|
||
- Vue Router 能正确找到路由配置
|
||
- 页面正常显示
|
||
|
||
2. **刷新页面**(直接访问 URL):
|
||
```
|
||
http://localhost:8080/system/post
|
||
```
|
||
- 浏览器直接请求该 URL
|
||
- Vue Router 重新解析路由配置
|
||
- 如果子路由配置错误(`path: '/system/post'`),会被解析为根路径
|
||
- 最终匹配到 `/post`(错误)
|
||
|
||
### 修复后的行为
|
||
|
||
1. **首次导航**:
|
||
```javascript
|
||
router.push('/system/post')
|
||
```
|
||
- 匹配到:`/system` + `post` = `/system/post` ✅
|
||
|
||
2. **刷新页面**:
|
||
```
|
||
http://localhost:8080/system/post
|
||
```
|
||
- 匹配到:`/system` + `post` = `/system/post` ✅
|
||
- 路由正常,页面正常显示
|
||
|
||
## 测试步骤
|
||
|
||
### 1. 刷新浏览器
|
||
清除前端缓存,重新加载路由配置(Ctrl+F5)。
|
||
|
||
### 2. 测试系统管理 - 岗位管理
|
||
1. 登录系统
|
||
2. 点击"系统管理" → "岗位管理"
|
||
3. URL 应该是:`http://localhost:8080/system/post`
|
||
4. 刷新页面(F5)
|
||
5. ✅ URL 保持不变:`http://localhost:8080/system/post`
|
||
6. ✅ 页面正常显示
|
||
|
||
### 3. 测试其他路由
|
||
测试以下路由,确保刷新后 URL 不变:
|
||
- `http://localhost:8080/system/staff`
|
||
- `http://localhost:8080/system/tenant`
|
||
- `http://localhost:8080/userManage/user`
|
||
- `http://localhost:8080/userManage/driver`
|
||
- `http://localhost:8080/userManage/vehicle`
|
||
- `http://localhost:8080/hardware/collar`
|
||
- `http://localhost:8080/hardware/eartag`
|
||
- `http://localhost:8080/hardware/host`
|
||
- `http://localhost:8080/permission/menu`
|
||
- `http://localhost:8080/permission/operation`
|
||
- `http://localhost:8080/shipping/loadingOrder`
|
||
- `http://localhost:8080/shipping/shippinglist`
|
||
- `http://localhost:8080/earlywarning/earlywarninglist`
|
||
|
||
### 4. 验证浏览器前进/后退
|
||
1. 依次访问多个页面
|
||
2. 点击浏览器"后退"按钮
|
||
3. ✅ URL 应该正确回到前一个页面
|
||
4. 点击浏览器"前进"按钮
|
||
5. ✅ URL 应该正确前进到下一个页面
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 为什么之前能正常跳转,但刷新就不行?
|
||
**答**:
|
||
- `router.push()` 跳转时,Vue Router 使用编程式导航,能够容错
|
||
- 刷新页面时,浏览器直接请求 URL,Vue Router 严格按照配置解析
|
||
- 如果配置错误(使用绝对路径),刷新时就会出错
|
||
|
||
### Q2: 什么时候应该使用绝对路径(以 `/` 开头)?
|
||
**答**:
|
||
- **几乎不需要**
|
||
- 仅在子路由确实需要在根路径下时才使用
|
||
- 99% 的嵌套路由应该使用相对路径
|
||
|
||
### Q3: 如何判断路由配置是否正确?
|
||
**答**:
|
||
检查子路由的 `path` 是否以 `/` 开头:
|
||
```javascript
|
||
// ❌ 错误
|
||
children: [
|
||
{ path: '/parent/child' } // 不应该包含父路径
|
||
]
|
||
|
||
// ✅ 正确
|
||
children: [
|
||
{ path: 'child' } // 只写相对路径
|
||
]
|
||
```
|
||
|
||
### Q4: 修复后需要重启开发服务器吗?
|
||
**答**:
|
||
- 如果使用 Vite(本项目),通常会自动热更新
|
||
- 如果没有生效,强制刷新浏览器(Ctrl+F5)
|
||
- 必要时重启开发服务器:`npm run dev`
|
||
|
||
## Vue Router 最佳实践
|
||
|
||
### ✅ 推荐做法
|
||
|
||
1. **嵌套路由使用相对路径**
|
||
```javascript
|
||
{
|
||
path: '/parent',
|
||
children: [
|
||
{ path: 'child' } // ✅ 相对路径
|
||
]
|
||
}
|
||
```
|
||
|
||
2. **顶级路由使用绝对路径**
|
||
```javascript
|
||
{
|
||
path: '/login' // ✅ 顶级路由必须以 / 开头
|
||
}
|
||
```
|
||
|
||
3. **使用命名路由**
|
||
```javascript
|
||
{
|
||
path: 'post',
|
||
name: 'Post' // ✅ 方便编程式导航
|
||
}
|
||
```
|
||
|
||
4. **路由导航使用 name**
|
||
```javascript
|
||
router.push({ name: 'Post' }) // ✅ 推荐
|
||
router.push('/system/post') // 也可以,但不推荐
|
||
```
|
||
|
||
### ❌ 避免的做法
|
||
|
||
1. **子路由使用绝对路径**
|
||
```javascript
|
||
{
|
||
path: '/parent',
|
||
children: [
|
||
{ path: '/parent/child' } // ❌ 错误
|
||
]
|
||
}
|
||
```
|
||
|
||
2. **路径拼写错误**
|
||
```javascript
|
||
{
|
||
path: 'post',
|
||
component: () => import('~/views/system/Post.vue') // ❌ 大小写错误
|
||
}
|
||
```
|
||
|
||
3. **路径与组件不匹配**
|
||
```javascript
|
||
{
|
||
path: 'post',
|
||
component: () => import('~/views/system/staff.vue') // ❌ 组件错误
|
||
}
|
||
```
|
||
|
||
## 总结
|
||
|
||
✅ **修复完成**:
|
||
- 所有嵌套路由的子路径已改为相对路径
|
||
- 刷新页面时 URL 不再变化
|
||
- 所有页面正常显示
|
||
|
||
✅ **关键原则**:
|
||
- **嵌套路由的子路径不要以 `/` 开头**
|
||
- Vue Router 会自动拼接父路径和子路径
|
||
- 相对路径配置简洁、清晰、不易出错
|
||
|
||
✅ **用户体验改善**:
|
||
- 刷新页面后 URL 保持不变
|
||
- 浏览器前进/后退功能正常
|
||
- 书签和分享链接正常工作
|
||
|