8.9 KiB
name, overview, todos, isProject
| name | overview | todos | isProject | |||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 修复Layout菜单操作失效 | 修复 Vue 2 到 Vue 3 迁移导致的 layout 菜单折叠/展开/关闭失效问题,根本原因是使用了 Vue 2 的 beforeDestroy 生命周期钩子,需要全部替换为 Vue 3 的 beforeUnmount |
|
false |
修复 Layout 菜单操作失效问题
问题根源
Vue 3 中,生命周期钩子名称发生了变化:
beforeDestroy→beforeUnmountdestroyed→unmounted
当前项目使用了 @vue/compat (Vue 3 兼容模式),但这些组件仍在使用 Vue 2 的生命周期钩子。这导致组件销毁时的清理代码(移除事件监听器)没有执行,从而导致:
- 侧边栏折叠/展开失效 -
[ResizeHandler.js](mom-backend-ui/src/layout/mixin/ResizeHandler.js)中的 resize 监听器没有正确清理 - 顶部菜单操作失效 -
[TopNav/index.vue](mom-backend-ui/src/components/TopNav/index.vue)中的 resize 监听器问题 - 右侧面板关闭失效 -
[RightPanel/index.vue](mom-backend-ui/src/components/RightPanel/index.vue)中的 click 监听器问题 - 全屏功能失效 -
[Screenfull/index.vue](mom-backend-ui/src/components/Screenfull/index.vue)中的监听器问题
影响范围
共 13 个文件使用了 beforeDestroy:
核心 Layout 相关(优先级 P0)
[src/layout/mixin/ResizeHandler.js](mom-backend-ui/src/layout/mixin/ResizeHandler.js)- 控制侧边栏响应式[src/components/TopNav/index.vue](mom-backend-ui/src/components/TopNav/index.vue)- 顶部菜单[src/components/Screenfull/index.vue](mom-backend-ui/src/components/Screenfull/index.vue)- 全屏功能[src/components/RightPanel/index.vue](mom-backend-ui/src/components/RightPanel/index.vue)- 右侧面板
其他组件(优先级 P1)
[src/components/Editor/index.vue](mom-backend-ui/src/components/Editor/index.vue)- 富文本编辑器[src/components/CountTo/index.vue](mom-backend-ui/src/components/CountTo/index.vue)- 数字动画
图表组件(优先级 P2)
src/views/dashboard/BarChart.vuesrc/views/dashboard/LineChart.vuesrc/views/dashboard/PieChart.vuesrc/views/dashboard/RaddarChart.vuesrc/views/mes/report/chart/chart.vuesrc/views/mes/report/chart/mixins/resize.jssrc/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.vuesrc/components/CountTo/index.vue
修改: beforeDestroy → beforeUnmount
7-13. 图表组件和 Mixins
文件:
src/views/dashboard/BarChart.vuesrc/views/dashboard/LineChart.vuesrc/views/dashboard/PieChart.vuesrc/views/dashboard/RaddarChart.vuesrc/views/mes/report/chart/chart.vuesrc/views/mes/report/chart/mixins/resize.jssrc/views/dashboard/mixins/resize.js
修改: beforeDestroy → beforeUnmount
影响: 修复图表组件的内存泄漏问题
验证方法
测试 1: 侧边栏折叠/展开
- 打开系统
- 点击左上角的 hamburger 图标(三条横线)
- 验证侧边栏正常折叠/展开
- 调整浏览器窗口大小
- 验证侧边栏在移动端自动收起
预期结果: 所有操作正常响应
测试 2: 顶部菜单
- 启用顶部菜单模式(在布局设置中)
- 点击顶部菜单项
- 验证菜单切换正常
- 调整浏览器窗口大小
- 验证菜单项自动折叠到"更多菜单"
预期结果: 菜单操作正常
测试 3: 全屏功能
- 点击顶部工具栏的全屏图标
- 验证进入全屏
- 再次点击退出全屏
- 验证图标状态正确切换
预期结果: 全屏功能正常
测试 4: 右侧面板
- 点击顶部的"布局设置"
- 验证右侧面板打开
- 点击面板外部区域
- 验证面板自动关闭
预期结果: 面板开关正常
测试 5: 控制台检查
打开浏览器控制台,执行以下检查:
- 切换不同页面
- 确认没有 "beforeDestroy is deprecated" 警告
- 确认没有内存泄漏警告
- 确认事件监听器正确添加和移除
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 |
无变化 |
技术要点
为什么需要修复
- 事件监听器泄漏:
beforeDestroy未执行导致removeEventListener没有调用 - 内存泄漏: 未清理的监听器持续占用内存
- 功能失效: 新的事件监听器无法正常工作
- 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
预期效果
修复后:
- ✅ 侧边栏折叠/展开正常工作
- ✅ 顶部菜单响应式正常
- ✅ 全屏功能正常
- ✅ 右侧面板开关正常
- ✅ 无内存泄漏
- ✅ 无控制台警告
后续建议
- 全局搜索其他 Vue 2 语法:
grep -r "beforeDestroy\|destroyed\|\$listeners\|\$on\|\$off" --include="*.vue" --include="*.js"
- 考虑完全迁移到 Vue 3:
- 移除
@vue/compat依赖 - 使用纯 Vue 3 API
- 更新所有组件库到最新版本
- 添加 ESLint 规则: 检测和阻止使用已弃用的 Vue 2 API