【Vue3 + ECharts 实战】正确使用 showLoading、resize 与 dispose 避免内存泄漏

在开发基于 Vue3 的大屏数据可视化系统时,ECharts 是我们最常使用的图表库之一。然而,若不注意其生命周期管理,很容易出现 图表无法响应窗口缩放、重复加载卡顿、甚至内存泄漏 等问题。

本文将结合一个真实的灌区信息化系统代码片段(index.vue),深入讲解如何在 Vue3 中 正确使用 showLoadingresizedispose ,并配合 onMountedonBeforeUnmount 生命周期钩子,构建健壮、高性能的 ECharts 图表组件。


一、背景:一个典型的大屏页面结构

在你的 index.vue 中,页面包含多个 ECharts 图表区域:

  • 雨情监测(rainChartBox
  • 水情监测(waterChartBox
  • 水量分析(amountChartBox

每个图表都需要:

  1. 初始化
  2. 加载数据前显示 loading
  3. 响应浏览器窗口大小变化
  4. 组件销毁时释放资源

为此,代码中定义了一个 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 已挂载(放在 onMountednextTick 中)
不清理 resize 监听 导致多次绑定,resize 触发 N 次

五、总结

在 Vue3 + ECharts 的大屏项目中,资源管理和生命周期控制至关重要。通过:

  • 合理使用 showLoading / hideLoading 提升体验
  • 监听 resize 并调用 resize() 保证响应式
  • onBeforeUnmountdispose() 实例并移除监听
相关推荐
moshuying19 小时前
别让AI焦虑,偷走你本该有的底气
前端·人工智能
GIS之路20 小时前
ArcPy,一个基于 Python 的 GIS 开发库简介
前端
可夫小子21 小时前
OpenClaw基础-为什么会有两个端口
前端
喝拿铁写前端21 小时前
Dify 构建 FE 工作流:前端团队可复用 AI 工作流实战
前端·人工智能
喝咖啡的女孩1 天前
React 合成事件系统
前端
从文处安1 天前
「九九八十一难」组合式函数到底有什么用?
前端·vue.js
用户5962585736061 天前
戴上AI眼镜逛花市——感受不一样的体验
前端
yuki_uix1 天前
Props、Context、EventBus、状态管理:组件通信方案选择指南
前端·javascript·react.js
老板我改不动了1 天前
前端面试复习指南【代码演示多多版】之——HTML
前端
panshihao1 天前
Mac 环境下通过 SSH 操作服务器,完成前端静态资源备份与更新(全程实操无坑)
前端