【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() 实例并移除监听
相关推荐
涵涵(互关)17 小时前
语法大全-only-writer-two
前端·vue.js·typescript
huangql52017 小时前
浏览器 Location API、History API、路由记录与支付跳转完全指南
前端
木斯佳17 小时前
前端八股文面经大全:腾讯前端实习一面(2026-04-27)·面经深度解析
前端·八股·面经
sayamber17 小时前
Kubernetes 生产环境避坑指南:10 个真实故障案例与解决方案
前端
清寒_17 小时前
分层理解AI架构,降低对AI复杂度的恐惧
前端·人工智能·ai编程
神探小白牙17 小时前
echarts,3d堆叠图
android·3d·echarts
牧码岛18 小时前
Web前端之JavaScrip中的Array、Object、Map和Set详解
前端·javascript·web·web前端
Bigger18 小时前
😮‍💨 有了 AI 之后,我怎么感觉反而更累了?
前端·aigc·ai编程
Dxy123931021618 小时前
HTML中使用Canvas动态图形渲染:解锁Web交互新维度
前端·html·图形渲染
西陵18 小时前
如何实现 Claude 生成式 UI?一套可落地的工程方案
前端·人工智能·ai编程