Files
my-mom-system/.cursor/plans/修复layout菜单操作失效_99a7ebb5.plan.md
panchengyong c28ada5050 commit content
2026-03-06 02:02:59 +08:00

8.9 KiB
Raw Permalink Blame History

name, overview, todos, isProject
name overview todos isProject
修复Layout菜单操作失效 修复 Vue 2 到 Vue 3 迁移导致的 layout 菜单折叠/展开/关闭失效问题,根本原因是使用了 Vue 2 的 beforeDestroy 生命周期钩子,需要全部替换为 Vue 3 的 beforeUnmount
id content status
fix-resize-handler 修复 ResizeHandler.js: beforeDestroy → beforeUnmount completed
id content status
fix-topnav 修复 TopNav/index.vue: beforeDestroy → beforeUnmount completed
id content status
fix-screenfull 修复 Screenfull/index.vue: beforeDestroy → beforeUnmount completed
id content status
fix-rightpanel 修复 RightPanel/index.vue: beforeDestroy → beforeUnmount completed
id content status
fix-editor-countto 修复 Editor 和 CountTo 组件: beforeDestroy → beforeUnmount completed
id content status
fix-chart-components 修复所有图表组件和 mixins: beforeDestroy → beforeUnmount completed
id content status
verify-layout 验证侧边栏、顶部菜单、全屏、右侧面板功能 completed
false

修复 Layout 菜单操作失效问题

问题根源

Vue 3 中,生命周期钩子名称发生了变化:

  • beforeDestroybeforeUnmount
  • destroyedunmounted

当前项目使用了 @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 行:

// 修复前
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 行:

// 修复前
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 行:

// 修复前
beforeDestroy() {
  this.destroy()
},

// 修复后
beforeUnmount() {
  this.destroy()
},

影响: 修复全屏功能


4. RightPanel 组件

文件: [src/components/RightPanel/index.vue](mom-backend-ui/src/components/RightPanel/index.vue)

第 59-62 行:

// 修复前
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

修改: beforeDestroybeforeUnmount


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

修改: beforeDestroybeforeUnmount

影响: 修复图表组件的内存泄漏问题

验证方法

测试 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 语法

影响分析

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 语法:
 grep -r "beforeDestroy\|destroyed\|\$listeners\|\$on\|\$off" --include="*.vue" --include="*.js"
  1. 考虑完全迁移到 Vue 3:
  • 移除 @vue/compat 依赖
  • 使用纯 Vue 3 API
  • 更新所有组件库到最新版本
  1. 添加 ESLint 规则: 检测和阻止使用已弃用的 Vue 2 API