Files
admin_core/demo-project/首页路由梳理说明.md
张成 7e888970d3 1
2025-10-08 19:20:24 +08:00

428 lines
9.7 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.
# 首页路由梳理说明
## 🔍 问题分析
### 原来的问题
首页在多个地方被设置,导致路由混乱和错误:
1. **`src/utils/uiTool.js``getRoutes` 方法**
- 接收了 `HomePage` 参数但没有使用
- `children` 初始化为空数组
- 尝试查找不存在的 `homeRoute`,返回 `undefined`
- 使用 `undefined` 导致路由错误
2. **`src/index.js``install` 方法**
- 调用 `getRoutes` 创建路由
- 传入了 `HomePage` 但没有被使用
3. **`demo-project/src/main.js``mounted` 钩子**
- 又调用了 `setAuthorityMenus` 重新设置菜单
- 导致路由被重复设置
### 错误信息
```
vue-router.esm.js:1396 Uncaught TypeError: Cannot read properties of undefined (reading 'path')
[vuex] unknown action type: getSysTitle
[vuex] unknown getter: sysFormModel
```
## ✅ 解决方案
### 设计原则
1. **单一职责**:每个方法只负责一件事
2. **避免重复**:路由只在一个地方创建和设置
3. **清晰的流程**:首页设置流程清晰可追踪
### 新的首页设置流程
```
应用启动
框架 install 方法
调用 getRoutes 创建主路由
创建默认首页路由 (/home)
检查 localStorage 中的权限菜单
如果有权限菜单,合并到主路由
创建 VueRouter 实例
应用启动完成
用户登录
保存权限菜单到 localStorage
刷新页面
重新执行上述流程(此时有权限菜单)
```
## 📝 修改内容
### 1. 修复 `src/utils/uiTool.js` 的 `getRoutes` 方法
**修改前**
```javascript
static getRoutes(Main, ParentView, Page404, HomePage) {
let mainRoute = {
path: '/',
name: '主视图',
redirect: '/home',
component: Main,
meta: { title: '首页', notCache: true },
children: [] // ❌ 空数组,没有默认首页
}
// ... 后续逻辑尝试使用不存在的 homeRoute
const homeRoute = mainRoute.children.find(r => r.name === 'home') // ❌ undefined
mainRoute.children = [homeRoute, ...curRoutes] // ❌ 使用 undefined
}
```
**修改后**
```javascript
static getRoutes(Main, ParentView, Page404, HomePage) {
// ✅ 创建默认的首页路由
const defaultHomeRoute = {
path: '/home',
name: 'home',
meta: { title: '首页', notCache: true },
component: HomePage || {
render: h => h('div', { style: { padding: '20px' } }, '欢迎使用管理系统')
}
}
let mainRoute = {
path: '/',
name: '主视图',
redirect: '/home',
component: Main,
meta: { title: '首页', notCache: true },
children: [defaultHomeRoute] // ✅ 包含默认首页
}
// 从 localStorage 读取权限菜单
if (localStorage.authorityMenus && localStorage.authorityMenus !== 'undefined') {
let authorityMenus = JSON.parse(localStorage.authorityMenus) || []
if (authorityMenus && authorityMenus.length > 0) {
let menus = uiTool.transformTree(authorityMenus)
let curRoutes = uiTool.menuToRoute(menus, ParentView, Page404)
// 检查权限路由中是否有 home
const hasHome = curRoutes.some(r => r.name === 'home')
if (hasHome) {
// 如果权限路由中有 home使用权限路由的 home
mainRoute.children = curRoutes
} else {
// 如果权限路由中没有 home保留默认 home 并添加其他路由
mainRoute.children = [defaultHomeRoute, ...curRoutes]
}
}
}
return mainRoute
}
```
**改进点**
- ✅ 使用传入的 `HomePage` 参数
- ✅ 创建默认的首页路由
- ✅ 正确处理权限菜单的合并
- ✅ 避免使用 `undefined`
### 2. 简化 `demo-project/src/main.js`
**修改前**
```javascript
window.rootVue = new Vue({
el: '#app',
router: AdminFramework.router,
store: AdminFramework.store,
render: h => h(App),
mounted() {
AdminFramework.uiTool.setRem()
// ❌ 重复设置权限菜单
this.$store.dispatch('user/setAuthorityMenus', {
Main: AdminFramework.Main,
ParentView: AdminFramework.ParentView,
Page404: AdminFramework.Page404
})
this.$store.dispatch('app/getSysTitle', {
defaultTitle: 'Demo 管理系统',
defaultLogo: ''
})
}
})
```
**修改后**
```javascript
window.rootVue = new Vue({
el: '#app',
router: AdminFramework.router,
store: AdminFramework.store,
render: h => h(App),
mounted() {
AdminFramework.uiTool.setRem()
// ✅ 只获取系统标题,不重复设置菜单
this.$store.dispatch('app/getSysTitle', {
defaultTitle: 'Demo 管理系统',
defaultLogo: ''
})
}
})
```
**改进点**
- ✅ 移除了重复的 `setAuthorityMenus` 调用
- ✅ 路由只在框架初始化时创建一次
- ✅ 登录后通过刷新页面重新加载路由
### 3. 修复 Vuex 模块命名空间问题
**修改的文件**
- `src/components/main/main.vue`
- `src/components/main/components/user/user.vue`
**修改前**
```javascript
// main.vue
...mapGetters({
sysFormModel: 'sysFormModel', // ❌ 缺少模块前缀
menuList: 'menuList',
userName: 'userName',
userAvator: 'avatorImgPath'
})
// user.vue
...mapActions(['handleLogOut']) // ❌ 缺少模块前缀
```
**修改后**
```javascript
// main.vue
...mapGetters({
sysFormModel: 'app/sysFormModel', // ✅ 添加模块前缀
menuList: 'user/menuList',
userName: 'user/userName',
userAvator: 'user/avatorImgPath'
})
// user.vue
...mapActions('user', ['handleLogOut']) // ✅ 指定模块
```
## 🎯 完整的首页路由流程
### 首次访问(未登录)
```
1. 用户访问 http://localhost:8080
2. 框架初始化
3. getRoutes 创建主路由
- localStorage 中没有 authorityMenus
- 使用默认首页路由
4. 路由配置:
{
path: '/',
component: Main,
children: [
{ path: '/home', name: 'home', component: HomePage }
]
}
5. 显示登录页面
```
### 登录流程
```
1. 用户输入用户名密码
2. 调用登录接口
3. 保存 token 和用户信息
4. 调用 setAuthorityMenus
- 尝试获取权限菜单(可能失败)
- 使用默认菜单配置
- 保存到 localStorage
5. 刷新页面 (window.location.reload())
6. 重新执行首次访问流程
- 此时 localStorage 中有 authorityMenus
- 根据权限菜单生成路由
```
### 登录后访问
```
1. 用户访问 http://localhost:8080
2. 框架初始化
3. getRoutes 创建主路由
- localStorage 中有 authorityMenus
- 解析权限菜单
- 生成权限路由
4. 路由配置:
{
path: '/',
component: Main,
children: [
{ path: '/home', name: 'home', component: HomePage },
{ path: '/system/user', name: 'sys_user', component: SysUser },
{ path: '/system/role', name: 'sys_role', component: SysRole },
// ... 其他权限路由
]
}
5. 显示系统首页
```
## 📊 路由结构
### 完整的路由树
```
routes: [
// 登录页面
{
path: '/login',
name: 'login',
component: LoginPage
},
// 主路由
{
path: '/',
name: '主视图',
redirect: '/home',
component: Main,
children: [
// 默认首页
{
path: '/home',
name: 'home',
component: HomePage,
meta: { title: '首页', notCache: true }
},
// 权限路由(从 authorityMenus 生成)
{
path: '/system/user',
name: 'sys_user',
component: SysUser,
meta: { title: '用户管理' }
},
{
path: '/system/role',
name: 'sys_role',
component: SysRole,
meta: { title: '角色管理' }
},
// ... 更多权限路由
]
},
// 错误页面
{
path: '/401',
name: 'error_401',
component: Page401
},
{
path: '/500',
name: 'error_500',
component: Page500
},
{
path: '*',
name: 'error_404',
component: Page404
}
]
```
## ✅ 验证清单
### 功能验证
- ✅ 首次访问显示登录页面
- ✅ 登录成功后跳转到首页
- ✅ 首页正确显示
- ✅ 左侧菜单正确显示
- ✅ 系统标题正确显示
- ✅ 用户名正确显示
- ✅ 页面跳转正常
- ✅ 刷新页面后状态保持
### 错误修复
- ✅ 修复了 `Cannot read properties of undefined (reading 'path')` 错误
- ✅ 修复了 `[vuex] unknown action type: getSysTitle` 错误
- ✅ 修复了 `[vuex] unknown getter: sysFormModel` 错误
- ✅ 修复了首页路由重复设置的问题
## 💡 最佳实践
### 1. 路由创建原则
- **单一入口**:路由只在框架初始化时创建一次
- **数据驱动**:根据 localStorage 中的数据动态生成路由
- **默认兜底**:始终提供默认的首页路由
### 2. 权限菜单处理
- **登录时保存**:登录成功后保存权限菜单到 localStorage
- **启动时读取**:应用启动时从 localStorage 读取权限菜单
- **刷新更新**:登录后刷新页面,重新生成路由
### 3. 避免的陷阱
- ❌ 不要在多个地方创建或修改路由
- ❌ 不要在 mounted 钩子中重复设置菜单
- ❌ 不要忘记处理 undefined 的情况
- ❌ 不要忘记 Vuex 模块的命名空间
## 🎉 总结
### 修复的问题
1. ✅ 首页路由正确创建
2. ✅ 权限菜单正确合并
3. ✅ 避免了重复设置
4. ✅ 修复了 Vuex 命名空间问题
5. ✅ 流程清晰可维护
### 代码改进
- **减少复杂度**:移除了重复的菜单设置逻辑
- **提高可读性**:流程更清晰,易于理解
- **增强健壮性**:正确处理各种边界情况
- **符合规范**:遵循 Vue 和 Vuex 的最佳实践
---
**首页路由梳理完成!** 🎉
现在路由创建流程清晰、简洁、可靠。