Vue 3 图表自适应核心是用ResizeObserver监听容器content-box变化并调用chartInstance.resize(),封装为useEChartsResize组合式函数,要求容器显式设置宽高,再结合adaptOption动态调整配置项。

Vue 3 中实现图表尺寸自适应的通用封装,核心在于解耦“尺寸监听”与“图表重绘”,避免每个图表组件重复写 resize 逻辑、手动绑 window 事件或处理侧边栏折叠等边界情况。关键不是靠 CSS 拉伸,而是让 ECharts 实例感知容器真实变化并主动响应。
用 ResizeObserver 替代 window.resize
传统监听 window.resize 有明显缺陷:无法捕获侧边栏收起、Flex 容器收缩、Tab 切换后容器重排等非窗口级变化;且频繁触发易造成性能抖动。现代方案应直接监听图表容器 DOM 节点本身:
- 在组件 setup 中通过 ref 获取 chart 容器元素
- 使用 ResizeObserver 实例观察该容器的 content-box 尺寸变化
- 回调中调用 chartInstance.resize(),不需防抖(浏览器已做队列合并)
- 组件卸载时记得 observer.unobserve() 和 disconnect(),防止内存泄漏
把尺寸适配逻辑抽成可复用的组合式函数
不建议把 ResizeObserver 写死在每个图表组件里。推荐封装为 useEChartsResize 组合式函数:
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 接收 chartInstance 和容器 ref 作为参数
- 内部创建 observer 并绑定监听逻辑
- 返回一个 dispose 方法,供 onBeforeUnmount 调用
- 父组件只需 import 并调用一次,逻辑完全复用
容器样式必须明确宽高,且不能依赖浮动或内容撑开
ECharts 初始化和 resize 都依赖容器的 clientWidth/clientHeight。如果容器没有显式尺寸,echarts.init 可能拿到 0:
立即学习“前端免费学习笔记(深入)”;
- 模板中容器 div 必须设置 width/height(如 100%, 400px 或 flex: 1)
- 避免父级 display: contents 或 position: absolute 导致脱离文档流
- 若用 flex 布局,确保父容器有高度约束(如 height: 100vh 或 min-height)
- 不要依赖 padding 或 border 触发重绘——ResizeObserver 监听的是 content-box,不是 border-box
配合 option 动态计算,让图表真正“适配”而非“拉伸”
单纯 resize() 只是重绘画布,字体、间距、图例位置仍可能失真。进阶做法是结合容器尺寸动态调整配置项:
- 监听容器宽度,在 setOption 前根据 width 计算 fontSize、legend.right、grid.left 等值
- 对饼图 radius、柱状图 barWidth 等数值型配置,按比例缩放(如 width > 1200 ? '60%' : '40%')
- 将这类计算逻辑封装进一个 adaptOption 工具函数,接收原始 option 和 containerRect,返回适配后配置

















