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;
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
}
}
// types.ts
export enum RenderType {
SVGRenderer = 'SVGRenderer',
CanvasRenderer = 'SVGRenderer'
}
export enum ThemeType {
Light = 'light',
Dark = 'dark',
Default = 'default'
}
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>
npm
github repo : https://github.com/QC2168/useCharts
npm install echart @qc2168/use-charts
Top comments (0)