Files
admin_core/demo-project/路由重复导航警告修复.md
张成 99f73eff84 1
2025-10-08 19:30:09 +08:00

410 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 路由重复导航警告修复
## 🔍 问题描述
控制台出现警告:
```
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" 警告
- ✅ 路由跳转更加流畅
- ✅ 用户体验更好
---
**路由重复导航警告已修复!** 🎉
现在控制台不会再出现重复导航的警告了。