ECharts 简介

动态数据与异步加载

掌握 setOption 的合并更新机制、loading 动画、接口数据加载和图表自适应 resize。

🎯 引言

真实项目里,数据不会写死在代码里,而是从接口获取、甚至实时刷新。学会这篇文章,你能掌握 setOption 的更新机制、加载动画、异步数据渲染和窗口自适应,让图表在真实业务里跑起来。


🧱 setOption 的合并机制

更新图表不用重新 init,再调一次 setOption 就行。默认是合并模式:新配置和旧配置合并,只有变化的部分会更新,还自带过渡动画:

// 初始渲染
chart.setOption({
    xAxis: { type: 'category', data: ['周一', '周二'] },
    series: [{ type: 'bar', data: [120, 200] }],
});

// 数据变化后,只传要更新的部分
chart.setOption({
    series: [{ data: [150, 260] }],
});
合并模式下,新数据是“覆盖合并”而不是清空。如果新数据比旧数据短(比如从 7 天变成 3 天),多余的旧数据可能残留。这时可以传第二个参数 true,表示不合并、整体替换:
chart.setOption(option, true);

🧱 加载动画 loading

接口请求有耗时,期间给用户一个转圈提示,体验会好很多:

chart.showLoading(); // 显示加载动画

// 数据回来后
chart.hideLoading(); // 关闭加载动画
chart.setOption({ series: [{ data: list }] });

🛠 从接口加载数据

结合 axios(不熟悉可以回顾本站的 Axios 课程),完整流程是:显示 loading → 请求 → 更新图表 → 关闭 loading:

views/SalesChart.vue
<template>
    <div ref="chartRef" class="chart"></div>
</template>

<script setup>
import { onMounted, ref } from 'vue';
import * as echarts from 'echarts';
import axios from 'axios';

const chartRef = ref(null);
let chart = null;

const fetchData = async () => {
    chart.showLoading();

    const res = await axios.get('/api/sales/weekly');
    const { days, values } = res.data;

    chart.hideLoading();
    chart.setOption({
        xAxis: { data: days },
        series: [{ data: values }],
    });
};

onMounted(() => {
    chart = echarts.init(chartRef.value);

    // 先给空数据,让图表骨架先出来
    chart.setOption({
        title: { text: '一周销量' },
        tooltip: { trigger: 'axis' },
        xAxis: { type: 'category', data: [] },
        yAxis: { type: 'value' },
        series: [{ name: '销量', type: 'bar', data: [] }],
    });

    fetchData();
});
</script>

<style scoped>
.chart {
    width: 100%;
    height: 400px;
}
</style>

注意这里的套路:先给空数据让图表骨架渲染出来,接口返回后再填充,页面不会长时间空白。

需要定时刷新(比如监控大屏)时,用 setInterval 周期性调用 fetchData,记得在组件卸载时 clearInterval

🧱 窗口自适应 resize

浏览器窗口变化时,图表不会自动跟随缩放,需要监听 resize 事件手动调整:

const handleResize = () => {
    chart.resize();
};

onMounted(() => {
    window.addEventListener('resize', handleResize);
});

onBeforeUnmount(() => {
    window.removeEventListener('resize', handleResize);
});

漏掉这一步,窗口一缩放图表就会溢出或者留白。


🧾 小节总结

  • 再次调用 setOption 即可更新图表,默认合并模式,只更新变化的部分。
  • 新数据可能比旧数据短时,用 setOption(option, true) 整体替换。
  • showLoading / hideLoading 在请求前后包裹,提升等待体验。
  • 异步套路:先空数据渲染骨架 → 接口返回 → 再 setOption 填充。
  • 监听窗口 resize 事件调用 chart.resize(),组件卸载时移除监听。

❓ 知识问答

Q1:setOption 会重新初始化图表吗?

不会。它在原实例上增量更新,性能很好,频繁调用也没问题。

Q2:接口返回的数据格式和 ECharts 需要的不一样怎么办?

在拿到响应后先做一次数据转换(比如用 map 拆出 days 和 values 两个数组),再交给 setOption

Q3:loading 动画样式能改吗?

可以,showLoading 接收一个配置对象,能改文字、颜色、遮罩。初学阶段用默认样式即可。

Q4:为什么图表在弹窗、抽屉里尺寸不对?

容器显示前后尺寸变了,但图表没有重算。在容器显示之后手动调一次 chart.resize() 即可。


🧪 小练习

模拟一个 1 秒后返回数据的接口,完成异步加载全流程:

  1. 先渲染一个空数据的折线图骨架。
  2. setTimeout 模拟接口,1 秒后返回 7 天数据。
  3. 等待期间显示 loading,数据到达后关闭并更新图表。
onMounted(() => {
    const chart = echarts.init(chartRef.value);

    // 请在这里编写代码
});

🎉 恭喜你已经能让图表对接真实数据了!下一篇我们把这些经验沉淀成一个可复用的 Vue3 图表组件,并学会按需引入减小打包体积。