【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() 实例并移除监听
相关推荐
小彭努力中1 天前
191.Vue3 + OpenLayers 实战:可控化版权信息(Attribution)详解与完整示例
前端·javascript·vue.js·#地图开发·#cesium
奇舞精选1 天前
用去年 github 最火的 n8n 快速实现自动化推送工具
前端·agent
奇舞精选1 天前
实践:如何为智能体推理引入外部决策步骤
前端·agent
无限大61 天前
AI实战02:一个万能提示词模板,搞定90%的文案/设计/分析需求
前端·后端
朝阳5811 天前
控制 Nuxt 页面的渲染模式:客户端 vs 服务端渲染
前端·javascript
发现一只大呆瓜1 天前
Vue-Vue2与Vue3核心差异与进化
前端·vue.js·面试
sunny_1 天前
熬夜通宵读完 VitePlus 全部源码,我后悔没早点看
前端·前端框架·前端工程化
发现一只大呆瓜1 天前
Vue2:数组/对象操作避坑大全
前端·vue.js·面试
发现一只大呆瓜1 天前
Vue3:ref 与 reactive 超全对比
前端·vue.js·面试
lzksword1 天前
C++ Builder XE OpenDialog1打开多文件并显示xls与xlsx二种格式文件
java·前端·c++