Frontend Development 6 min read

Integrating ECharts with Vue 3 and TypeScript: A Practical Guide

This article demonstrates how to set up and use ECharts in a Vue 3 project with TypeScript, providing a reusable library, type definitions, a composable hook, and example components to render various chart types efficiently.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Integrating ECharts with Vue 3 and TypeScript: A Practical Guide

Introduction

The article covers the use of TypeScript, Vue 3, and ECharts for building customizable data visualizations, explaining why a reusable component is not provided and each chart requires its own option configuration.

Project Structure

|--src
    |--components
        |--echarts            // ECharts wrapper directory
            |--echarts-types.ts    // Type definitions
            |--library.ts          // Core ECharts imports and registration
            |--useECharts.ts       // Main composable function
        |--EChartsComponents
            |--a-echarts.vue      // Example component usage
    |--App.vue

library.ts

This file imports core ECharts modules, registers required charts and components, and exports the configured ECharts instance.

import * as echarts from 'echarts/core';
import {
        BarChart,
        LineChart,
        PieChart,
        MapChart,
        PictorialBarChart,
        RadarChart,
        ScatterChart
} from 'echarts/charts';
import {
        TitleComponent,
        TooltipComponent,
        GridComponent,
        PolarComponent,
        AriaComponent,
        ParallelComponent,
        LegendComponent,
        RadarComponent,
        ToolboxComponent,
        DataZoomComponent,
        VisualMapComponent,
        TimelineComponent,
        CalendarComponent,
        GraphicComponent
} from 'echarts/components';

echarts.use([
        LegendComponent,
        TitleComponent,
        TooltipComponent,
        GridComponent,
        PolarComponent,
        AriaComponent,
        ParallelComponent,
        BarChart,
        LineChart,
        PieChart,
        MapChart,
        RadarChart,
        PictorialBarChart,
        RadarComponent,
        ToolboxComponent,
        DataZoomComponent,
        VisualMapComponent,
        TimelineComponent,
        CalendarComponent,
        GraphicComponent,
        ScatterChart
]);

export default echarts;

echarts-types.ts

Defines enums for renderer type and theme.

export enum RenderType {
        SVGRenderer = 'SVGRenderer',
        CanvasRenderer = 'SVGRenderer'
}

export enum ThemeType {
        Light = 'light',
        Default = 'default',
}

useECharts.ts

The composable hook initializes the chart, provides methods to set options, show/hide loading, handle resizing, and expose the chart instance.

import { onMounted, onUnmounted, Ref, unref } from "vue";
import echarts from "./library";
// import type { EChartsOption } from 'echarts'
import { SVGRenderer, CanvasRenderer } from 'echarts/renderers'
import { RenderType, ThemeType } from './echarts-types'

export function useECharts(elparams: Ref
| HTMLDivElement, autoUpdateSize: boolean = false, render: RenderType = RenderType.SVGRenderer, theme = ThemeType.Default) {
        // Set renderer
        echarts.use(render === RenderType.SVGRenderer ? SVGRenderer : CanvasRenderer)
        let echartsInstance: echarts.ECharts | null = null
        function initCharts() {
                const el = unref(elparams)
                if (!el) return
                echartsInstance = echarts.init(el, theme)
        }
        function setOption(option: any) {
                showLoading()
                if (!echartsInstance) initCharts()
                if (!echartsInstance) return
                echartsInstance.setOption(option)
                hideLoading()
        }
        function getInstance() {
                if (!echartsInstance) initCharts()
                return echartsInstance
        }
        function onResize() {
                echartsInstance?.resize()
        }
        function watchEl() {
                if (animation) unref(elparams).style.transition = 'width 1s, height 1s'
                const resizeObserve = new ResizeObserver(() => onResize())
                resizeObserve.observe(unref(elparams))
        }
        function showLoading() {
                if (!echartsInstance) initCharts()
                echartsInstance?.showLoading()
        }
        function hideLoading() {
                if (!echartsInstance) initCharts()
                echartsInstance?.hideLoading()
        }
        onMounted(() => {
                window.addEventListener('resize', onResize)
                if (autoUpdateSize) watchEl()
        })
        onUnmounted(() => {
                window.removeEventListener('resize', onResize)
        })
        return { setOptions, getInstance }
}

Component Usage

a-echarts.vue

Template and script that mount the chart and apply an option.

<template>
        <div class="chart" ref="MyEcharts"></div>
</template>

<script lang="ts" setup>
import { onMounted, Ref, ref } from "vue";
import echarts from "../echarts/library";
// Get ECharts instance
const MyEcharts = ref<HTMLDivElement | null>(null)
const { setOption, getInstance } = useECharts(MyEcharts as Ref<HTMLDivElement>, false, true)
onMounted(() => {
        setOption(option);
        const echartsInstance = getInstance()
})
</script>

App.vue

Root component that includes the chart component.

<template>
  <echarts></echarts>
</template>
<script setup lang="ts">
import echarts from './components/EchartsComponents/a-echarts.vue'
</script>
<style scoped></style>

The article ends with a call for likes and follows, indicating that the tutorial is intended to help developers quickly integrate ECharts into Vue 3 projects.

frontendtypescriptJavaScriptData VisualizationEChartsVue3
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.