This commit is contained in:
张成
2025-10-08 19:30:09 +08:00
parent 7e888970d3
commit 99f73eff84
6 changed files with 1339 additions and 3 deletions

View 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" 警告
- ✅ 路由跳转更加流畅
- ✅ 用户体验更好
---
**路由重复导航警告已修复!** 🎉
现在控制台不会再出现重复导航的警告了。