DEV Community

Cover image for How to use echart chart more gracefully in Vue3
山田
山田

Posted on • Originally published at juejin.cn

How to use echart chart more gracefully in Vue3

preface

In large screen visualization projects, we often need to use a lot of chart components. Usually, you will write a lot of 'options' to render charts, and import some of the components they need and usechart.use.

In Vue2, we often separate reusable components, and then pass the data required by the components to the reusable components through props,emits and other methods. In Vue3, we can write some logical functions as hooks for extraction and reuse, and then pass them to the view. This will not only make the code in your components more elegant but also more readable.

thinking

import modules

We first create a lib. ts file to import and export all the components needed in the' chart '.

Because there are too many modules introduced, we extract the code of the modules it introduces to increase the readability of the code

// lib.ts
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;

Enter fullscreen mode Exit fullscreen mode

Encapsulation function

Create a useChart. ts file in the same level directory. and reuse the echartook file.

feature:

  • Monitor chart element changes and views, and automatically re render the chart to adapt to the height
  • Theme and rendering mode can be imported (SVG, Canvas)
  • loading effect
import { nextTick, onMounted, onUnmounted, Ref, unref } from "vue";
import type { EChartsOption } from 'echarts';
import echarts from "./lib";
import { SVGRenderer, CanvasRenderer } from "echarts/renderers";
import { RenderType, ThemeType } from "./types";

export default function useChart(elRef: Ref<HTMLDivElement>, autoChartSize = false, animation: boolean = false, render: RenderType = RenderType.SVGRenderer, theme: ThemeType = ThemeType.Default) {
    // render mode
    echarts.use(render === RenderType.SVGRenderer ? SVGRenderer : CanvasRenderer)
    // echart instance
    let chartInstance: echarts.ECharts | null = null;

    // init echart
    const initCharts = () => {
        const el = unref(elRef)
        if (!el || !unref(el)) {
            return
        }
        chartInstance = echarts.init(el, theme);
    }

    // update or set options
    const setOption = (option: EChartsOption) => {
        nextTick(() => {
            if (!chartInstance) {
                initCharts();
                if (!chartInstance) return;
            }

            chartInstance.setOption(option)
            hideLoading()
        })

    }

    // get echart instance
    function getInstance(): echarts.ECharts | null {
        if (!chartInstance) {
            initCharts();
        }
        return chartInstance;
    }

    // resize cheats
    function resize() {
        chartInstance?.resize();
    }

    // observe chart
    function watchEl() {
        // add animation effect
        if (animation) { elRef.value.style.transition = 'width 1s, height 1s' }
        const resizeObserver = new ResizeObserver((entries => resize()))
        resizeObserver.observe(elRef.value);
    }

    // show loading
    function showLoading() {
        if (!chartInstance) {
            initCharts();
        }
        chartInstance?.showLoading()
    }
    // hide loading
    function hideLoading() {
        if (!chartInstance) {
            initCharts();
        }
        chartInstance?.hideLoading()
    }

    onMounted(() => {
        window.addEventListener('resize', resize)
        if (autoChartSize) watchEl();
    })

    onUnmounted(() => {
        window.removeEventListener('resize', resize)
    })

    return {
        setOption,
        getInstance,
        showLoading,
        hideLoading
    }
}
Enter fullscreen mode Exit fullscreen mode
// types.ts
export enum RenderType {
    SVGRenderer = 'SVGRenderer',
    CanvasRenderer = 'SVGRenderer'
}
export enum ThemeType {
    Light = 'light',
    Dark = 'dark',
    Default = 'default'
}
Enter fullscreen mode Exit fullscreen mode

With the above encapsulated code, it will be simpler and more efficient to use the 'chart' library in components.

e.g

// index.vue
<template>
    <div ref="chartEl" :style="{ width: `300px`, height: `300px` }"></div>
</template>

<script setup lang="ts">
import { onMounted, Ref, ref, computed, nextTick } from "vue";
import type { EChartsOption } from 'echarts'
import useChart, { RenderType, ThemeType } from '../../useChart'
import axios from 'axios'

const option = computed<EChartsOption>(() => ({
   // ...chart option
}))

const chartEl = ref<HTMLDivElement | null>(null)

const {
    setOption,
    showLoading
} = useChart(chartEl as Ref<HTMLDivElement>, true, true, RenderType.SVGRenderer, ThemeType.Dark)



onMounted(() => {
    nextTick(() => {
        // show loading
        showLoading()
        // request data ...
        // render
        setOption(option.value);
    })
})

</script>
Enter fullscreen mode Exit fullscreen mode

npm

github repo : https://github.com/QC2168/useCharts

npm install echart @qc2168/use-charts

Top comments (0)