深浅主题
ECharts 隐藏容器尺寸异常
问题现象
图表初次打开为空白,宽度为零,切换 Tab 后只有半张图;浏览器调整大小后恢复。
适用环境
ECharts 5/6、Vue 3;Tab、抽屉或折叠区中的图表。
本文是可复用的排障示例,不代表某次个人生产事故。命令中的名称、账号和数据均为示例,执行前请替换为已确认的目标。
复现或诊断步骤
- 在 echarts.init 前打印容器 getBoundingClientRect,确认宽高大于零。
- 检查父元素是否 display:none、未设置高度,或正处于展开动画。
- 查看是否对同一 DOM 重复 init,确认实例是否仍绑定旧 DOM。
原因分析
图表根据初始化时的容器尺寸布局。隐藏容器无法提供有效宽度;DOM 更新、字体加载或侧栏变化后,窗口尺寸未变化,所以 window.resize 不一定触发。
修复示例
ts
import * as echarts from 'echarts'
import { ref, nextTick, onMounted, onUnmounted } from 'vue'
const host = ref<HTMLElement>()
let chart: echarts.ECharts | undefined
let observer: ResizeObserver | undefined
async function syncChart() {
await nextTick()
const el = host.value
if (!el || !el.clientWidth || !el.clientHeight) return
chart ??= echarts.init(el)
chart.resize()
}
onMounted(() => {
observer = new ResizeObserver(syncChart)
if (host.value) observer.observe(host.value)
syncChart()
})
onUnmounted(() => { observer?.disconnect(); chart?.dispose() })模板容器显式设置高度,例如 360px,并在业务 Tab 激活后调用 syncChart。setOption 放在实例创建和数据就绪之后,避免每次尺寸变化都重新请求数据。Observer 回调不要反过来持续修改容器宽高。
验证方法
检查首次显示、隐藏再显示、侧栏折叠、手机旋转和离开页面。对比容器尺寸与 canvas 尺寸,确认实例数量不随 Tab 切换增长。
常见误区
固定延迟 500ms 依赖设备速度,不能保证展开结束。不要通过每次 dispose/init 修复布局,也不要只给 canvas 设置 CSS 宽度而忽略实例 resize。