從數據可視化開始:用 ECharts 把枯燥數據變成直觀圖表大屏實戰指南

做後台系統或營運大屏的前端工程師,大概都有過這種時刻:後端丟來一張幾千行的報表,老闆盯著密密麻麻的數字皺眉頭,你卻在想——同樣的數據,如果能變成一根會說話的柱子、一條會拐彎的曲線,溝通成本起碼少一半。數據可視化不是把圖畫漂亮這麼簡單,它是把「人腦難以處理的資訊」翻譯成「人眼一眼就懂的語言」。這篇文章延續「從 X 開始」實戰指南系列,帶你用 ECharts 在 Vue 3 專案裡,從零把數據變成能上牆的圖表大屏。

一、為什麼前端工程師也要懂可視化

很多團隊把圖表當成「順手加一下」的附屬品,結果做出來的圖要麼卡頓、要麼和設計稿對不上。其實可視化有三個容易被忽略的價值:

  • 降維打擊:時間序列、分布、佔比,圖表一眼勝過千行表格。
  • 異常顯性化:告警數據用紅綠熱力圖,誰都能秒懂哪裡出問題。
  • 決策加速器:大屏讓管理者在 3 秒內抓住重點,而不是翻 10 頁報表。

對做威脅情報、資產監控這類「數據即戰場」的系統,可視化幾乎是剛需。

二、ECharts 是什麼:一張圖表背後的引擎

ECharts 是百度開源、現由 Apache 基金會維護的視覺化庫,基於 Canvas/WebGL 渲染,支援折線、柱狀、散點、地圖、關係圖等幾十種圖表。它的核心心智模型很簡單:你只要描述「數據長什麼樣」和「想要什麼樣式」,剩下的渲染交給它。比起手刻 SVG,ECharts 在大數據量、動畫、自適應上都省下大量功夫。

三、步驟 1:在 Vue 3 專案中安裝與引入

先安裝依賴(以 Vite + Vue 3 為例):

npm install echarts

為了避免全量引入導致打包體積膨脹,重點:在 Vite 這類建置工具下,建議用按需引入(echarts/core + 具體圖表/元件),只註冊你用到的模組:

// echarts.ts
import * as echarts from 'echarts/core';
import { BarChart, LineChart } from 'echarts/charts';
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

echarts.use([
  BarChart,
  LineChart,
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  CanvasRenderer,
]);

export default echarts;

四、步驟 2:封裝一個可複用的圖表組件

圖表組件的重點是「掛載時初始化、數據變化時 setOption、卸載時 dispose」,否則會記憶體洩漏:

<template>
  <div ref="chartRef" :style="{ width: '100%', height: height }"></div>
</template>

<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref, watch } from 'vue';
import echarts from '@/utils/echarts';

const props = defineProps<{
  option: Record<string, unknown>;
  height?: string;
}>();

const chartRef = ref<HTMLDivElement>();
let chart: echarts.ECharts | null = null;

onMounted(() => {
  if (!chartRef.value) return;
  chart = echarts.init(chartRef.value);
  chart.setOption(props.option);
});

watch(
  () => props.option,
  (opt) => chart && chart.setOption(opt, true),
  { deep: true },
);

onBeforeUnmount(() => {
  chart?.dispose();
  chart = null;
});
</script>

五、步驟 3:接 API 動態渲染與自適應

實戰中數據幾乎都來自介面。用 useTable 或 fetch 拿到資料後,組成 ECharts 的 option 物件即可:

import { ref, onMounted, onBeforeUnmount } from 'vue';

const option = ref({});
const dailyCounts = ref<{ date: string; count: number }[]>([]);

async function loadData() {
  const res = await fetch('/api/log/daily-counts');
  dailyCounts.value = await res.json();
  option.value = {
    tooltip: { trigger: 'axis' },
    xAxis: { type: 'category', data: dailyCounts.value.map((d) => d.date) },
    yAxis: { type: 'value' },
    series: [
      { type: 'bar', data: dailyCounts.value.map((d) => d.count), itemStyle: { color: '#22d3ee' } },
    ],
  };
}

// 重點:容器尺寸變化時必須呼叫 resize,否則圖表會被壓扁或留白
let ro: ResizeObserver | null = null;
onMounted(() => {
  loadData();
  const el = chartRef.value!;
  ro = new ResizeObserver(() => chart?.resize());
  ro.observe(el);
});
onBeforeUnmount(() => ro?.disconnect());

六、步驟 4:打造大屏的幾個實戰技巧

大屏和一般報表不同,它要「遠看有氣勢、近看有細節」:

  • 深色毛玻璃底:用半透明卡片 + 青色邊框,讓圖表像浮在控制檯上。
  • 呼吸脈衝動畫:對告警類指標用 animationDuration + 陰影脈衝,引導視線。
  • 統一調色板:全站定義一套主色,避免圖表各畫各的。
  • 地圖疊加:威脅來源這類地理數據,用 ECharts 的 geo/map 系列直接上「3D 地球」或平面世界地圖。

七、常見坑與效能注意

特別注意:大數據量(上萬點)時,優先用 dataset + appendData 或開啟 large: true 的散點模式,必要時切到 WebGL 渲染器;同時每個圖表實例都要 dispose,切頁不釋放就會記憶體堆積。另外,option 頻繁更新時用 setOption(opt, true) 而非合併,能避免舊系列殘留。

數據可視化是一道「技術 + 設計 + 業務理解」的複合題。把上面的組件封裝好、把自適應與釋放做紮實,你就能在半天內搭出一面讓老闆點頭的大屏。

互動話題:你在專案裡最頭痛的圖表場景是什麼?是大數據量卡頓、還是設計稿還原度不夠?留言告訴我,我們一起拆。