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