--- name: 修复Layout菜单操作失效 overview: 修复 Vue 2 到 Vue 3 迁移导致的 layout 菜单折叠/展开/关闭失效问题,根本原因是使用了 Vue 2 的 beforeDestroy 生命周期钩子,需要全部替换为 Vue 3 的 beforeUnmount todos: - id: fix-resize-handler content: "修复 ResizeHandler.js: beforeDestroy → beforeUnmount" status: completed - id: fix-topnav content: "修复 TopNav/index.vue: beforeDestroy → beforeUnmount" status: completed - id: fix-screenfull content: "修复 Screenfull/index.vue: beforeDestroy → beforeUnmount" status: completed - id: fix-rightpanel content: "修复 RightPanel/index.vue: beforeDestroy → beforeUnmount" status: completed - id: fix-editor-countto content: "修复 Editor 和 CountTo 组件: beforeDestroy → beforeUnmount" status: completed - id: fix-chart-components content: "修复所有图表组件和 mixins: beforeDestroy → beforeUnmount" status: completed - id: verify-layout content: 验证侧边栏、顶部菜单、全屏、右侧面板功能 status: completed isProject: false --- # 修复 Layout 菜单操作失效问题 ## 问题根源 Vue 3 中,生命周期钩子名称发生了变化: - `beforeDestroy` → `beforeUnmount` - `destroyed` → `unmounted` 当前项目使用了 `@vue/compat` (Vue 3 兼容模式),但这些组件仍在使用 Vue 2 的生命周期钩子。这导致组件销毁时的清理代码(移除事件监听器)没有执行,从而导致: 1. **侧边栏折叠/展开失效** - `[ResizeHandler.js](mom-backend-ui/src/layout/mixin/ResizeHandler.js)` 中的 resize 监听器没有正确清理 2. **顶部菜单操作失效** - `[TopNav/index.vue](mom-backend-ui/src/components/TopNav/index.vue)` 中的 resize 监听器问题 3. **右侧面板关闭失效** - `[RightPanel/index.vue](mom-backend-ui/src/components/RightPanel/index.vue)` 中的 click 监听器问题 4. **全屏功能失效** - `[Screenfull/index.vue](mom-backend-ui/src/components/Screenfull/index.vue)` 中的监听器问题 ## 影响范围 共 13 个文件使用了 `beforeDestroy`: ### 核心 Layout 相关(优先级 P0) 1. `[src/layout/mixin/ResizeHandler.js](mom-backend-ui/src/layout/mixin/ResizeHandler.js)` - 控制侧边栏响应式 2. `[src/components/TopNav/index.vue](mom-backend-ui/src/components/TopNav/index.vue)` - 顶部菜单 3. `[src/components/Screenfull/index.vue](mom-backend-ui/src/components/Screenfull/index.vue)` - 全屏功能 4. `[src/components/RightPanel/index.vue](mom-backend-ui/src/components/RightPanel/index.vue)` - 右侧面板 ### 其他组件(优先级 P1) 1. `[src/components/Editor/index.vue](mom-backend-ui/src/components/Editor/index.vue)` - 富文本编辑器 2. `[src/components/CountTo/index.vue](mom-backend-ui/src/components/CountTo/index.vue)` - 数字动画 ### 图表组件(优先级 P2) 1. `src/views/dashboard/BarChart.vue` 2. `src/views/dashboard/LineChart.vue` 3. `src/views/dashboard/PieChart.vue` 4. `src/views/dashboard/RaddarChart.vue` 5. `src/views/mes/report/chart/chart.vue` 6. `src/views/mes/report/chart/mixins/resize.js` 7. `src/views/dashboard/mixins/resize.js` ## 修复方案 ### 方案:批量替换生命周期钩子 所有文件中的 `beforeDestroy` 直接替换为 `beforeUnmount`。 ### 具体修改 #### 1. ResizeHandler Mixin **文件**: `[src/layout/mixin/ResizeHandler.js](mom-backend-ui/src/layout/mixin/ResizeHandler.js)` **第 17-19 行**: ```javascript // 修复前 beforeDestroy() { window.removeEventListener('resize', this.$_resizeHandler) }, // 修复后 beforeUnmount() { window.removeEventListener('resize', this.$_resizeHandler) }, ``` **影响**: 修复侧边栏折叠/展开功能 --- #### 2. TopNav 组件 **文件**: `[src/components/TopNav/index.vue](mom-backend-ui/src/components/TopNav/index.vue)` **第 107-109 行**: ```javascript // 修复前 beforeDestroy() { window.removeEventListener('resize', this.setVisibleNumber) }, // 修复后 beforeUnmount() { window.removeEventListener('resize', this.setVisibleNumber) }, ``` **影响**: 修复顶部菜单响应式 --- #### 3. Screenfull 组件 **文件**: `[src/components/Screenfull/index.vue](mom-backend-ui/src/components/Screenfull/index.vue)` **第 20-22 行**: ```javascript // 修复前 beforeDestroy() { this.destroy() }, // 修复后 beforeUnmount() { this.destroy() }, ``` **影响**: 修复全屏功能 --- #### 4. RightPanel 组件 **文件**: `[src/components/RightPanel/index.vue](mom-backend-ui/src/components/RightPanel/index.vue)` **第 59-62 行**: ```javascript // 修复前 beforeDestroy() { const elx = this.$refs.rightPanel elx.remove() }, // 修复后 beforeUnmount() { const elx = this.$refs.rightPanel elx.remove() }, ``` **影响**: 修复右侧面板关闭功能 --- #### 5-6. Editor 和 CountTo 组件 **文件**: - `src/components/Editor/index.vue` - `src/components/CountTo/index.vue` **修改**: `beforeDestroy` → `beforeUnmount` --- #### 7-13. 图表组件和 Mixins **文件**: - `src/views/dashboard/BarChart.vue` - `src/views/dashboard/LineChart.vue` - `src/views/dashboard/PieChart.vue` - `src/views/dashboard/RaddarChart.vue` - `src/views/mes/report/chart/chart.vue` - `src/views/mes/report/chart/mixins/resize.js` - `src/views/dashboard/mixins/resize.js` **修改**: `beforeDestroy` → `beforeUnmount` **影响**: 修复图表组件的内存泄漏问题 ## 验证方法 ### 测试 1: 侧边栏折叠/展开 1. 打开系统 2. 点击左上角的 hamburger 图标(三条横线) 3. 验证侧边栏正常折叠/展开 4. 调整浏览器窗口大小 5. 验证侧边栏在移动端自动收起 **预期结果**: 所有操作正常响应 --- ### 测试 2: 顶部菜单 1. 启用顶部菜单模式(在布局设置中) 2. 点击顶部菜单项 3. 验证菜单切换正常 4. 调整浏览器窗口大小 5. 验证菜单项自动折叠到"更多菜单" **预期结果**: 菜单操作正常 --- ### 测试 3: 全屏功能 1. 点击顶部工具栏的全屏图标 2. 验证进入全屏 3. 再次点击退出全屏 4. 验证图标状态正确切换 **预期结果**: 全屏功能正常 --- ### 测试 4: 右侧面板 1. 点击顶部的"布局设置" 2. 验证右侧面板打开 3. 点击面板外部区域 4. 验证面板自动关闭 **预期结果**: 面板开关正常 --- ### 测试 5: 控制台检查 打开浏览器控制台,执行以下检查: 1. 切换不同页面 2. 确认没有 "beforeDestroy is deprecated" 警告 3. 确认没有内存泄漏警告 4. 确认事件监听器正确添加和移除 ## Vue 3 生命周期对照表 | Vue 2 | Vue 3 | 说明 | | --------------- | --------------- | -------- | | `beforeCreate` | `beforeCreate` | 无变化 | | `created` | `created` | 无变化 | | `beforeMount` | `beforeMount` | 无变化 | | `mounted` | `mounted` | 无变化 | | `beforeUpdate` | `beforeUpdate` | 无变化 | | `updated` | `updated` | 无变化 | | `beforeDestroy` | `beforeUnmount` | **已重命名** | | `destroyed` | `unmounted` | **已重命名** | | `activated` | `activated` | 无变化 | | `deactivated` | `deactivated` | 无变化 | | `errorCaptured` | `errorCaptured` | 无变化 | ## 技术要点 ### 为什么需要修复 1. **事件监听器泄漏**: `beforeDestroy` 未执行导致 `removeEventListener` 没有调用 2. **内存泄漏**: 未清理的监听器持续占用内存 3. **功能失效**: 新的事件监听器无法正常工作 4. **Vue 3 兼容性**: `@vue/compat` 不完全支持 Vue 2 语法 ### 影响分析 ```mermaid graph TD A[组件挂载] --> B[添加事件监听器] B --> C[组件使用中] C --> D[组件卸载] D --> E{生命周期钩子} E -->|Vue 2: beforeDestroy| F[执行清理代码] E -->|Vue 3: beforeUnmount| F E -->|使用错误钩子| G[清理代码未执行] G --> H[监听器未移除] H --> I[功能失效] H --> J[内存泄漏] F --> K[监听器正确移除] K --> L[功能正常] ``` ## 修复优先级 ### P0 - 立即修复(影响核心功能) - ResizeHandler.js - TopNav/index.vue - Screenfull/index.vue - RightPanel/index.vue ### P1 - 高优先级(影响用户体验) - Editor/index.vue - CountTo/index.vue ### P2 - 中优先级(影响特定页面) - 所有图表组件和 mixins ## 预期效果 修复后: - ✅ 侧边栏折叠/展开正常工作 - ✅ 顶部菜单响应式正常 - ✅ 全屏功能正常 - ✅ 右侧面板开关正常 - ✅ 无内存泄漏 - ✅ 无控制台警告 ## 后续建议 1. **全局搜索其他 Vue 2 语法**: ```bash grep -r "beforeDestroy\|destroyed\|\$listeners\|\$on\|\$off" --include="*.vue" --include="*.js" ``` 2. **考虑完全迁移到 Vue 3**: - 移除 `@vue/compat` 依赖 - 使用纯 Vue 3 API - 更新所有组件库到最新版本 3. **添加 ESLint 规则**: 检测和阻止使用已弃用的 Vue 2 API