在开发基于 Vue3 的大屏数据可视化系统时,ECharts 是我们最常使用的图表库之一。然而,若不注意其生命周期管理,很容易出现 图表无法响应窗口缩放、重复加载卡顿、甚至内存泄漏 等问题。
本文将结合一个真实的灌区信息化系统代码片段(index.vue),深入讲解如何在 Vue3 中 正确使用 showLoading、resize 和 dispose ,并配合 onMounted 与 onBeforeUnmount 生命周期钩子,构建健壮、高性能的 ECharts 图表组件。
一、背景:一个典型的大屏页面结构
在你的 index.vue 中,页面包含多个 ECharts 图表区域:
- 雨情监测(
rainChartBox) - 水情监测(
waterChartBox) - 水量分析(
amountChartBox)
每个图表都需要:
- 初始化
- 加载数据前显示 loading
- 响应浏览器窗口大小变化
- 组件销毁时释放资源
为此,代码中定义了一个 chart 对象来统一管理实例:
const chart = {
rainChart: null,
waterChart: null,
amountChart: null
}
二、关键方法解析
1. showLoading():优雅地展示加载状态
作用:在异步请求数据期间,显示"加载中"提示,提升用户体验。
用法示例(以水情图为例):
if (!chart.waterChart) {
chart.waterChart = markRaw(echarts.init(document.getElementById('waterChartBox')))
}
chart.waterChart.showLoading({
text: '加载中...',
color: '#0b8ee6',
textColor: '#fff',
maskColor: 'rgba(0, 0, 0, 0.3)',
zlevel: 0
});
✅ 最佳实践:
- 在发起 API 请求之前 调用
showLoading - 使用
markRaw包裹 ECharts 实例,避免 Vue 响应式系统追踪(提升性能) - 自定义 loading 样式,匹配 UI 风格
⚠️ 注意:即使接口失败或无数据,也必须调用
hideLoading(),否则 loading 会一直显示!
2. resize():响应窗口尺寸变化
大屏系统常需全屏展示,用户可能拖动浏览器窗口或切换分辨率。若不处理,图表会变形或留白。
解决方案 :监听 window.resize 事件,批量调用所有图表的 resize()。
const handleResize = () => {
Object.keys(chart).forEach(key => {
chart[key] && chart[key].resize();
});
};
onMounted(() => {
window.addEventListener('resize', handleResize);
});
onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize);
});
✅ 关键点:
- 只在
onMounted中添加监听器 - 必须在
onBeforeUnmount中移除监听器,防止内存泄漏 - 使用
Object.values(chart).forEach(...)批量处理,避免重复代码
3. dispose():释放资源,防止内存泄漏
ECharts 实例会占用 DOM 和内存。如果组件被销毁(如路由切换),但未调用 dispose(),会导致:
- 内存持续增长(尤其在 SPA 中频繁切换页面)
- 控制台报错(尝试操作已销毁的 DOM)
正确做法:
onBeforeUnmount(() => {
// 关闭视频播放器(如有)
if (DHVideoPlayerRef1.value) {
DHVideoPlayerRef1.value.close();
}
// 清理所有 ECharts 实例
Object.values(chart).forEach(instance => {
if (instance) {
instance.dispose();
}
});
// 移除 resize 监听
window.removeEventListener('resize', handleResize);
});
✅ 为什么重要?
dispose()会清除内部定时器、事件绑定和 canvas 上下文- 避免"Cannot read property 'getAttribute' of null"等错误
- 是专业前端工程化的体现
三、完整生命周期流程图
四、常见误区与避坑指南
| 误区 | 正确做法 |
|---|---|
每次更新数据都 new echarts.init() |
复用已有实例,仅调用 setOption |
忘记 hideLoading |
在 .then 和 .catch 中都调用 hideLoading |
在 setup() 中直接操作 DOM |
确保 DOM 已挂载(放在 onMounted 或 nextTick 中) |
| 不清理 resize 监听 | 导致多次绑定,resize 触发 N 次 |
五、总结
在 Vue3 + ECharts 的大屏项目中,资源管理和生命周期控制至关重要。通过:
- 合理使用
showLoading/hideLoading提升体验 - 监听
resize并调用resize()保证响应式 - 在
onBeforeUnmount中dispose()实例并移除监听