1
This commit is contained in:
409
demo-project/_doc/路由重复导航警告修复.md
Normal file
409
demo-project/_doc/路由重复导航警告修复.md
Normal file
@@ -0,0 +1,409 @@
|
||||
# 路由重复导航警告修复
|
||||
|
||||
## 🔍 问题描述
|
||||
|
||||
控制台出现警告:
|
||||
```
|
||||
Avoided redundant navigation to current location: "/home".
|
||||
NavigationDuplicated: Avoided redundant navigation to current location: "/home".
|
||||
```
|
||||
|
||||
## 📋 问题原因
|
||||
|
||||
### 警告产生的场景
|
||||
|
||||
**场景 1:已在首页时访问登录页**
|
||||
```
|
||||
当前路由: /home
|
||||
↓
|
||||
用户访问: /login
|
||||
↓
|
||||
路由守卫检测到已登录
|
||||
↓
|
||||
尝试重定向: next({ name: 'home' })
|
||||
↓
|
||||
目标路由: /home
|
||||
↓
|
||||
❌ 警告:已经在 /home,避免重复导航
|
||||
```
|
||||
|
||||
**场景 2:刷新首页**
|
||||
```
|
||||
当前路由: /home
|
||||
↓
|
||||
刷新页面
|
||||
↓
|
||||
路由守卫再次执行
|
||||
↓
|
||||
检测到已登录且访问登录页(可能的中间状态)
|
||||
↓
|
||||
尝试重定向: next({ name: 'home' })
|
||||
↓
|
||||
❌ 警告:已经在 /home,避免重复导航
|
||||
```
|
||||
|
||||
### 原来的路由守卫代码
|
||||
|
||||
```javascript
|
||||
router.beforeEach((to, from, next) => {
|
||||
const token = getToken()
|
||||
ViewUI.LoadingBar.start()
|
||||
|
||||
if (to.name === 'view_log') {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
if (!token && to.name !== 'login') {
|
||||
next({ name: 'login' })
|
||||
} else if (!token && to.name === 'login') {
|
||||
next()
|
||||
} else if (token && to.name === 'login') {
|
||||
// ❌ 没有检查来源路由,可能导致重复导航
|
||||
next({ name: homeName })
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**问题**:
|
||||
- 当已登录用户访问登录页时,总是重定向到首页
|
||||
- 没有检查来源路由是否已经是首页
|
||||
- 导致重复导航警告
|
||||
|
||||
## ✅ 解决方案
|
||||
|
||||
### 修改路由守卫逻辑
|
||||
|
||||
**修改文件**:`src/router/index.js`
|
||||
|
||||
**修改后的代码**:
|
||||
```javascript
|
||||
router.beforeEach((to, from, next) => {
|
||||
const token = getToken()
|
||||
ViewUI.LoadingBar.start()
|
||||
|
||||
if (to.name === 'view_log') {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
if (!token && to.name !== 'login') {
|
||||
// 未登录且访问非登录页 → 跳转到登录页
|
||||
next({ name: 'login' })
|
||||
} else if (!token && to.name === 'login') {
|
||||
// 未登录且访问登录页 → 允许访问
|
||||
next()
|
||||
} else if (token && to.name === 'login') {
|
||||
// 已登录且访问登录页 → 重定向到首页
|
||||
// ✅ 避免重复导航警告
|
||||
if (from.name === homeName) {
|
||||
next(false) // 取消导航,停留在当前页面
|
||||
} else {
|
||||
next({ name: homeName }) // 重定向到首页
|
||||
}
|
||||
} else {
|
||||
// 其他情况 → 允许访问
|
||||
next()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 关键改进
|
||||
|
||||
**添加了来源路由检查**:
|
||||
```javascript
|
||||
if (from.name === homeName) {
|
||||
next(false) // 如果来自首页,取消导航
|
||||
} else {
|
||||
next({ name: homeName }) // 否则重定向到首页
|
||||
}
|
||||
```
|
||||
|
||||
**`next(false)` 的作用**:
|
||||
- 取消当前导航
|
||||
- 停留在当前页面(首页)
|
||||
- 不会触发重复导航警告
|
||||
|
||||
## 📊 修复后的流程
|
||||
|
||||
### 场景 1:从首页访问登录页
|
||||
|
||||
```
|
||||
当前路由: /home (from.name = 'home')
|
||||
↓
|
||||
用户访问: /login (to.name = 'login')
|
||||
↓
|
||||
路由守卫检测到已登录
|
||||
↓
|
||||
检查来源路由: from.name === 'home' ✅
|
||||
↓
|
||||
执行: next(false)
|
||||
↓
|
||||
取消导航,停留在首页 ✅
|
||||
↓
|
||||
✅ 没有警告
|
||||
```
|
||||
|
||||
### 场景 2:从其他页面访问登录页
|
||||
|
||||
```
|
||||
当前路由: /system/user (from.name = 'sys_user')
|
||||
↓
|
||||
用户访问: /login (to.name = 'login')
|
||||
↓
|
||||
路由守卫检测到已登录
|
||||
↓
|
||||
检查来源路由: from.name !== 'home' ✅
|
||||
↓
|
||||
执行: next({ name: 'home' })
|
||||
↓
|
||||
重定向到首页 ✅
|
||||
↓
|
||||
✅ 正常导航,没有警告
|
||||
```
|
||||
|
||||
### 场景 3:未登录访问登录页
|
||||
|
||||
```
|
||||
当前路由: 无 (from.name = undefined)
|
||||
↓
|
||||
用户访问: /login (to.name = 'login')
|
||||
↓
|
||||
路由守卫检测到未登录
|
||||
↓
|
||||
执行: next()
|
||||
↓
|
||||
允许访问登录页 ✅
|
||||
```
|
||||
|
||||
### 场景 4:登录成功后跳转
|
||||
|
||||
```
|
||||
登录成功
|
||||
↓
|
||||
执行: window.location.href = '#/'
|
||||
↓
|
||||
触发完整页面加载
|
||||
↓
|
||||
访问: / (重定向到 /home)
|
||||
↓
|
||||
路由守卫检测到已登录
|
||||
↓
|
||||
to.name = 'home' (不是 'login')
|
||||
↓
|
||||
执行: next()
|
||||
↓
|
||||
允许访问首页 ✅
|
||||
```
|
||||
|
||||
## 🎯 `next()` 方法说明
|
||||
|
||||
### `next()` 的不同用法
|
||||
|
||||
**1. `next()`**
|
||||
- 允许当前导航
|
||||
- 继续执行路由跳转
|
||||
|
||||
**2. `next(false)`**
|
||||
- 取消当前导航
|
||||
- 停留在当前页面
|
||||
- 不会触发路由变化
|
||||
|
||||
**3. `next({ name: 'home' })`**
|
||||
- 重定向到指定路由
|
||||
- 取消当前导航
|
||||
- 跳转到新路由
|
||||
|
||||
**4. `next({ path: '/home' })`**
|
||||
- 重定向到指定路径
|
||||
- 取消当前导航
|
||||
- 跳转到新路由
|
||||
|
||||
**5. `next(error)`**
|
||||
- 终止导航
|
||||
- 触发错误处理
|
||||
|
||||
### 为什么使用 `next(false)` 而不是 `next()`?
|
||||
|
||||
**如果使用 `next()`**:
|
||||
```javascript
|
||||
if (token && to.name === 'login') {
|
||||
next() // ❌ 允许访问登录页
|
||||
}
|
||||
```
|
||||
- 会允许已登录用户访问登录页
|
||||
- 不符合业务逻辑
|
||||
|
||||
**如果使用 `next({ name: homeName })`**:
|
||||
```javascript
|
||||
if (token && to.name === 'login') {
|
||||
next({ name: homeName }) // ❌ 如果已在首页,会重复导航
|
||||
}
|
||||
```
|
||||
- 如果来源路由已经是首页,会触发重复导航警告
|
||||
|
||||
**使用 `next(false)`**:
|
||||
```javascript
|
||||
if (token && to.name === 'login') {
|
||||
if (from.name === homeName) {
|
||||
next(false) // ✅ 取消导航,停留在首页
|
||||
} else {
|
||||
next({ name: homeName }) // ✅ 重定向到首页
|
||||
}
|
||||
}
|
||||
```
|
||||
- 如果来源是首页,取消导航,停留在首页
|
||||
- 如果来源不是首页,重定向到首页
|
||||
- 避免重复导航警告
|
||||
|
||||
## ✅ 验证清单
|
||||
|
||||
### 功能验证
|
||||
|
||||
- ✅ 未登录访问登录页 → 正常显示登录页
|
||||
- ✅ 未登录访问其他页面 → 重定向到登录页
|
||||
- ✅ 已登录访问登录页(从首页) → 停留在首页
|
||||
- ✅ 已登录访问登录页(从其他页面) → 重定向到首页
|
||||
- ✅ 登录成功 → 跳转到首页
|
||||
|
||||
### 警告检查
|
||||
|
||||
- ✅ 控制台没有 "Avoided redundant navigation" 警告
|
||||
- ✅ 控制台没有 "NavigationDuplicated" 警告
|
||||
- ✅ 路由跳转正常工作
|
||||
|
||||
### 边界情况
|
||||
|
||||
- ✅ 刷新首页 → 停留在首页
|
||||
- ✅ 刷新其他页面 → 停留在当前页面
|
||||
- ✅ 直接访问 URL → 正确处理
|
||||
|
||||
## 💡 最佳实践
|
||||
|
||||
### 1. 路由守卫中检查来源路由
|
||||
|
||||
**推荐**:
|
||||
```javascript
|
||||
if (token && to.name === 'login') {
|
||||
if (from.name === homeName) {
|
||||
next(false) // 来自首页,取消导航
|
||||
} else {
|
||||
next({ name: homeName }) // 来自其他页面,重定向
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**不推荐**:
|
||||
```javascript
|
||||
if (token && to.name === 'login') {
|
||||
next({ name: homeName }) // 可能导致重复导航
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 使用 `next(false)` 取消不必要的导航
|
||||
|
||||
**推荐**:
|
||||
```javascript
|
||||
if (shouldCancelNavigation) {
|
||||
next(false) // 取消导航
|
||||
}
|
||||
```
|
||||
|
||||
**不推荐**:
|
||||
```javascript
|
||||
if (shouldCancelNavigation) {
|
||||
// 什么都不做,导航会继续
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 避免在路由守卫中使用 `window.location`
|
||||
|
||||
**推荐**:
|
||||
```javascript
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (needRedirect) {
|
||||
next({ name: 'home' }) // 使用 next() 重定向
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**不推荐**:
|
||||
```javascript
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (needRedirect) {
|
||||
window.location.href = '#/home' // 不要在守卫中使用
|
||||
next(false)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 🔧 相关代码
|
||||
|
||||
### 完整的路由守卫代码
|
||||
|
||||
**文件**:`src/router/index.js`
|
||||
|
||||
```javascript
|
||||
// 路由守卫配置
|
||||
export const setupRouterGuards = (router, ViewUI, homeName = 'home') => {
|
||||
router.beforeEach((to, from, next) => {
|
||||
const token = getToken()
|
||||
ViewUI.LoadingBar.start()
|
||||
|
||||
if (to.name === 'view_log') {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
if (!token && to.name !== 'login') {
|
||||
// 未登录且访问非登录页 → 跳转到登录页
|
||||
next({ name: 'login' })
|
||||
} else if (!token && to.name === 'login') {
|
||||
// 未登录且访问登录页 → 允许访问
|
||||
next()
|
||||
} else if (token && to.name === 'login') {
|
||||
// 已登录且访问登录页 → 重定向到首页
|
||||
// 避免重复导航警告
|
||||
if (from.name === homeName) {
|
||||
next(false) // 来自首页,取消导航
|
||||
} else {
|
||||
next({ name: homeName }) // 来自其他页面,重定向到首页
|
||||
}
|
||||
} else {
|
||||
// 其他情况 → 允许访问
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
router.afterEach(to => {
|
||||
ViewUI.LoadingBar.finish()
|
||||
window.scrollTo(0, 0)
|
||||
})
|
||||
|
||||
return router
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 总结
|
||||
|
||||
### 修改内容
|
||||
|
||||
- ✅ 在路由守卫中添加了来源路由检查
|
||||
- ✅ 使用 `next(false)` 避免重复导航
|
||||
- ✅ 保持了原有的业务逻辑
|
||||
|
||||
### 效果
|
||||
|
||||
- ✅ 消除了 "Avoided redundant navigation" 警告
|
||||
- ✅ 消除了 "NavigationDuplicated" 警告
|
||||
- ✅ 路由跳转更加流畅
|
||||
- ✅ 用户体验更好
|
||||
|
||||
---
|
||||
|
||||
**路由重复导航警告已修复!** 🎉
|
||||
|
||||
现在控制台不会再出现重复导航的警告了。
|
||||
|
||||
Reference in New Issue
Block a user