在Vue3项目中优化使用ECharts的完整方案

 更新时间:2026年05月17日 15:33:00   作者:Pu_Nine_9  
在Vue3项目中使用 ECharts,如何做到按需打包、类型安全、响应式适配、自动销毁?本文分享一套可直接落地的封装方案,需要的朋友可以参考下

一、整体思路

  • 按需引入:只注册项目中用到的图表、组件、渲染器,减少打包体积。
  • 统一导出:封装一个 @/utils/echarts 模块,导出配置好的 echarts 实例和完整类型。
  • 组合式函数:编写 useECharts hook,自动处理 DOM 挂载、配置响应式更新、窗口/元素尺寸适配、生命周期清理。

二、文件 1:@/utils/echarts/index.ts—— 按需引入并导出

// TODO: 二次封装 ECharts 实例
import * as echarts from 'echarts/core'

// 引入使用的图表
import {
  BarChart,
  LineChart,
  PieChart
} from 'echarts/charts'

// 系列组件
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  VisualMapComponent,
  GeoComponent
} from 'echarts/components'

// 功能增强模块
import {
  LabelLayout,
  UniversalTransition
} from 'echarts/features'

// 渲染器
import { CanvasRenderer } from 'echarts/renderers'

// 注册所有必须组件
echarts.use([
  // 图表
  BarChart,
  LineChart,
  PieChart,
  // 组件
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  VisualMapComponent,
  GeoComponent,
  // 功能
  LabelLayout,
  UniversalTransition,
  // 渲染
  CanvasRenderer
])

// 导出类型
export * from '../../types'   // 这里指向你自己的全局类型文件,也可以直接导出 echarts 自带类型

// 导出手动封装后的 echarts
export { echarts }

说明:如果你的项目没有单独的 ../../types,可以直接改为导出 ECharts 的官方类型:

export type { ECharts, EChartsOption } from 'echarts'

三、文件 2:@/utils/echarts/types.ts—— 统一的 EChartsOption 类型(可选)

/**
 * 从 echarts/core 导入 ComposeOption 和 ECharts 类型
 * ComposeOption 是 ECharts 提供的类型组合工具,用于创建包含多种组件和图表类型的配置选项类型
 * ECharts 是 ECharts 实例的类型
 */
import type { ComposeOption } from 'echarts/core'

/**
 * 从 echarts/charts 导入图表系列类型
 */
import type {
  BarSeriesOption,
  LineSeriesOption,
  PieSeriesOption
} from 'echarts/charts'

/**
 * 从 echarts/components 导入组件配置类型
 */
import type {
  TitleComponentOption,
  TooltipComponentOption,
  LegendComponentOption,
  GridComponentOption,
  VisualMapComponentOption,
  GeoComponentOption
} from 'echarts/components'

/**
 * 导出具体的图表类型,方便在需要时单独使用
 */
export type { ECharts } from 'echarts/core'
export type {
  BarSeriesOption,
  LineSeriesOption,
  PieSeriesOption
} from 'echarts/charts'

/**
 * 统一的 EChartsOption 类型
 * 使用 ComposeOption 组合所有需要的类型,创建一个完整的配置选项类型
 * 这样可以获得更好的类型提示和类型检查
 */
export type EChartsOption = ComposeOption<
  | BarSeriesOption
  | LineSeriesOption
  | PieSeriesOption
  | TitleComponentOption
  | TooltipComponentOption
  | LegendComponentOption
  | GridComponentOption
  | VisualMapComponentOption
  | GeoComponentOption
>

说明:如果你的项目没有单独的类型文件,也可以直接使用 ECharts 官方导出的 EChartsOption,但上述手动组合可以精确控制可用组件,避免类型提示中出现未注册的组件。

四、文件 3:@/hooks/useECharts.ts—— 核心 Hook

import { ref, watch, onMounted, onUnmounted, unref, type Ref } from 'vue'
import { echarts } from '@/utils/echarts'
import type { EChartsOption, ECharts } from '@/utils/echarts'

/**
 * ECharts 图表 Hook
 * 自动初始化、响应式更新配置、自动销毁、窗口自适应
 *
 * @param elRef - 图表挂载的 DOM 引用(可以是 Ref 或原生 DOM 元素)
 * @param option - 图表配置项
 * @param autoResize - 是否自动跟随窗口大小变化,默认 true
 * @returns { chart, updateOption }
 */
export const useECharts = (
  elRef: Ref<HTMLElement | null> | HTMLElement | null | undefined,
  option: EChartsOption,
  autoResize = true
) => {
  const chart = ref<ECharts | null>(null)

  // 初始化图表
  const initChart = () => {
    const dom = unref(elRef)
    if (!dom) return
    chart.value = echarts.init(dom)
    chart.value.setOption(option)
  }

  // 更新配置
  const updateOption = (newOption: EChartsOption) => {
    chart.value?.setOption(newOption)
  }

  // 监听配置变化
  watch(
    () => option,
    () => updateOption(option),
    { deep: true }
  )

  // 监听 DOM 元素变化
  let resizeObserver: ResizeObserver | null = null
  const resize = () => chart.value?.resize()

  watch(
    () => unref(elRef),
    (newEl) => {
      if (newEl) {
        initChart()
        if (autoResize) {
          resizeObserver?.disconnect()
          resizeObserver = new ResizeObserver(resize)
          resizeObserver.observe(newEl)
        }
      }
    },
    { immediate: true }
  )

  // 组件挂载
  onMounted(() => {
    initChart()
    if (autoResize) {
      window.addEventListener('resize', resize)
      const dom = unref(elRef)
      if (dom) {
        resizeObserver = new ResizeObserver(resize)
        resizeObserver.observe(dom)
      }
    }
  })

  // 组件卸载
  onUnmounted(() => {
    if (autoResize) {
      window.removeEventListener('resize', resize)
      resizeObserver?.disconnect()
    }
    chart.value?.dispose()
    chart.value = null
  })

  return {
    chart: chart.value,
    updateOption,
  }
}

五、使用示例

5.1 基础用法

<template>
  <div ref="chartRef" style="width: 100%; height: 400px" />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useECharts } from '@/hooks/useECharts'
import type { EChartsOption } from '@/utils/echarts'

const chartRef = ref<HTMLElement>()

const option: EChartsOption = {
  title: { text: '月度销售趋势' },
  tooltip: {},
  xAxis: { type: 'category', data: ['1月', '2月', '3月', '4月'] },
  yAxis: { type: 'value' },
  series: [{ type: 'line', data: [120, 200, 150, 80] }]
}

const { chart, updateOption } = useECharts(chartRef, option, true)

// 模拟动态更新数据
setTimeout(() => {
  updateOption({
    series: [{ type: 'line', data: [300, 400, 250, 100] }]
  })
}, 3000)
</script>

5.2 响应式 option 自动更新

如果你的 option 是响应式数据(比如从 API 获取),且希望数据变化时图表自动更新,可以直接传入一个 refcomputed

<script setup>
import { ref } from 'vue'

const chartData = ref([120, 200, 150])
const option = computed(() => ({
  xAxis: { data: ['A', 'B', 'C'] },
  series: [{ type: 'bar', data: chartData.value }]
}))

const { chart } = useECharts(chartRef, option.value)
// 现在当 chartData 变化时,option 会重新计算,并触发 watch 自动调用 updateOption
</script>

5.3 手动控制 resize

如果某些场景下不需要自动 resize(比如弹窗中的图表),可以将第三个参数设为 false,然后手动调用 updateOption 中的 resize 逻辑(需要扩展 hook)。

六、方案优缺点总结

优点

  • 体积优化:按需引入,避免打包所有 ECharts 组件。
  • 类型安全:完整的 TypeScript 支持。
  • 自动适配:同时监听 window.resizeResizeObserver,覆盖大部分场景。
  • 生命周期安全:组件卸载时自动销毁图表实例,避免内存泄漏。
  • 响应式更新option 变化时自动重绘,无需手动调用。

待改进点(可根据项目需求继续完善)

  • 当前 chart 返回值是 chart.value(非响应式),建议改成 chart 本身的 ref,或提供 getChart 方法。
  • 缺少 ECharts 事件监听封装(如 on('click'))。
  • 缺少 loading 状态、错误处理、主题切换等企业级进阶功能。

你可以在此基础上按需扩展,例如:

// 增加事件监听
const on = (event: string, handler: any) => chart.value?.on(event, handler)
// 增加 loading
const showLoading = () => chart.value?.showLoading()
const hideLoading = () => chart.value?.hideLoading()

七、结语

这套封装已经在多个中大型 Vue 3 项目中实践,兼顾了灵活性、性能和开发体验。如果你正为 ECharts 集成发愁,不妨直接复制以上三个文件到你的项目中,再根据实际需求微调。

以上就是在Vue3项目中优化使用ECharts的完整方案的详细内容,更多关于Vue3优化使用ECharts的资料请关注脚本之家其它相关文章!

相关文章

  • vue项目实现页面跳转的方法

    vue项目实现页面跳转的方法

    这篇文章主要给大家分享的是vue项目实现页面跳转的方法,vue-router是前端开发中用来实现路由页面跳转的一个模块。下面小编将带来如何在已经创建好的vue-router项目基础下实现页面跳转,需要的朋友可以参考一下
    2021-11-11
  • vue在线动态切换主题色方案

    vue在线动态切换主题色方案

    这篇文章主要介绍了vue在线动态切换主题色方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • vue页面使用阿里oss上传功能的实例(二)

    vue页面使用阿里oss上传功能的实例(二)

    本篇文章主要介绍了vue页面使用阿里oss上传功能的实例(二),主要介绍OSS管理控制台设置访问权限、角色等,有兴趣的可以了解一下
    2017-08-08
  • vite打包拆分js和css的配置指南

    vite打包拆分js和css的配置指南

    这篇文章主要给大家介绍了关于vite打包拆分js和css的配置指南,Vite是一个非常快速的工具,它可以帮助你打包JavaScript文件,需要的朋友可以参考下
    2023-09-09
  • vue上传解析excel文件并在列表中输出内容

    vue上传解析excel文件并在列表中输出内容

    在vue的项目开发中,我们会遇到加载excel或者csv等情形,这个示例展示了这个需求,上传一个excel文件,通过解析,生成数组,然后再列表中将内容展示出来,这篇文章主要介绍了vue上传解析excel文件,列表中输出内容,需要的朋友可以参考下,
    2023-09-09
  • vue再次进入页面不会再次调用接口请求问题

    vue再次进入页面不会再次调用接口请求问题

    这篇文章主要介绍了vue再次进入页面不会再次调用接口请求问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 巧用Vue.js+Vuex制作专门收藏微信公众号的app

    巧用Vue.js+Vuex制作专门收藏微信公众号的app

    这篇文章主要为大家详细介绍了vue自定义指令三步如何实现数据拉取更新,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • vue前端代码如何通过maven打成jar包运行

    vue前端代码如何通过maven打成jar包运行

    这篇文章主要介绍了vue前端代码如何通过maven打成jar包运行问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • vite + electron-builder 打包配置详解

    vite + electron-builder 打包配置详解

    这篇文章主要为大家介绍了electron基于vite + electron-builder 打包配置详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Mac下安装vue

    Mac下安装vue

    本文给大家详细介绍了Mac下安装vue的方法,本文图文并茂给大家介绍的非常详细,需要的朋友可以参考下
    2018-04-04

最新评论