Vue3 custom Echars component comes with global configuration
<template> <div ref="chart" : :class="className" :style="{ height: height, width: width }"></div> </template> <script setup> import { ref, reactive, toRefs, onMounted, onBeforeUnmount,watch } from 'vue' import * as echarts from 'echarts'; // Pass parametersconst props = defineProps({ className: { type: String, default: 'chart' }, id: { type: String, default: 'chart' }, width: { type: String, default: '100%' }, height: { type: String, default: '280px' }, options: { type: Object, default: () => { } } }) const chart = ref(null); const createChart = () => { const myChart = (); = (, 'tdTheme') (,true); // (, true) ("resize", () => { () }) }; watch(() => , (options) => { if () { // Set true to clear the echart cache (options, true) } }, { deep: true }) onMounted(() => { createChart(); }); onBeforeUnmount(() => { ("resize", () => { () }) () = null }) </script>
import Echart from './components/echart/' import echarts from 'echarts' const app = createApp(App) // Mount echarts to global object.$echarts = echarts // Register global components('Echart', Echart)
Case
<template> <div ref="chart" style="width: 600px; height: 400px;"></div> </template> <script setup> import { ref, onMounted } from 'vue'; import * as echarts from 'echarts'; const chart = ref(null); const createChart = () => { const myChart = (); ({ xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [{ data: [120, 200, 150, 80, 70, 110, 130], type: 'bar' }] }); }; onMounted(() => { createChart(); }); </script>
vue3 encapsulation echarts component
During the development process, you need to encapsulate the echarts component, which is convenient for multiple use. The following is the detailed process of encapsulation.
Pre-action: Install echarts and resize-observer-polyfill plug-in
- Create a new file
import * as echarts from "echarts/core"; /** * The chart types used are introduced as needed here */ import { BarChart, LineChart, type LineSeriesOption, PieChart, type PieSeriesOption } from "echarts/charts"; /** * The configuration used is introduced as needed here * In particular, including MarkPoint markLine, etc., should also be used separately, otherwise it will not be displayed in the chart. */ import { LegendComponent, type LegendComponentOption, TitleComponent, //The definition of component types is ComponentOption type TitleComponentOption, TooltipComponent, type TooltipComponentOption, GridComponent, type GridComponentOption, DataZoomComponent, type DataZoomComponentOption, // Dataset Component DatasetComponent, type DatasetComponentOption, // Mark components MarkAreaComponent, type MarkAreaComponentOption, MarkLineComponent, type MarkLineComponentOption, MarkPointComponent, type MarkPointComponentOption, // Built-in data converter component (filter, sort) TransformComponent, } from "echarts/components"; import { LabelLayout, UniversalTransition } from "echarts/features"; import { CanvasRenderer } from "echarts/renderers"; import { ref, shallowRef, onMounted, onBeforeUnmount } from "vue"; import ResizeObserver from "resize-observer-polyfill"; import throttle from "lodash/throttle"; /** * The introduced configuration uses ComposeOption to combine an Option type with only required components and charts. */ export type ECOption = < | LineSeriesOption | PieSeriesOption | LegendComponentOption | TitleComponentOption | TooltipComponentOption | DataZoomComponentOption | GridComponentOption | DatasetComponentOption | MarkAreaComponentOption | MarkLineComponentOption | MarkPointComponentOption >; /** * Register components introduced on demand */ ([ LegendComponent, TitleComponent, TooltipComponent, GridComponent, DataZoomComponent, DatasetComponent, MarkAreaComponent, MarkLineComponent, MarkPointComponent, TransformComponent, BarChart, LineChart, PieChart, LabelLayout, UniversalTransition, CanvasRenderer, ]); export default function useChart() { const canvasEl = shallowRef(); const myChart = shallowRef(); /** * Monitor container width changes or browser window changes to automatically display echarts charts * The reason why you don't use ("resize", resizeFn) is that this method only listens to the browser window without changing * -No monitoring of the size changes of the container you are in. It is difficult to meet the needs of the development scenario */ const resizeObserver = ref<ResizeObserver>(); const bindResize = () => { const deboundResize = throttle(() => { ?.resize(); }, 500); = new ResizeObserver(() => { deboundResize(); // ?.resize(); }); (); }; // Unbind resize const unbindResize = () => { ?.unobserve(); }; onMounted(() => { /** * Register echarts and enable monitoring container size changes */ = (); bindResize(); }); onBeforeUnmount(() => { /** * Destroy listening and echarts */ unbindResize(); ?.dispose(); = null; }); return { myChart, canvasEl, }; }
- Page encapsulation
<template> <div> <div class="chart-container" :style="containerStyle"> <div v-show="dataEmptyFlag" class="chart-empty"> <span class="empty-title">No data yet</span> </div> <div ref="canvasEl" :style="containerStyle" /> <div v-show="loading" class="chart-loading"><Spin /></div> </div> </div> </template> <script setup lang="ts"> import { Spin } from "ant-design-vue"; import { ref, watch } from "vue"; import useChart from "./useECharts"; import type { ECOption } from "./useECharts"; interface ChartProps { containerStyle?: any; loading?: boolean; dataEmptyFlag?: boolean; options?: ECOption; } const props = withDefaults(defineProps<ChartProps>(), { containerStyle: { height: "990px", width: "100%", }, loading: false, dataEmptyFlag: false, }); const { myChart, canvasEl } = useChart(); watch( () => props?.options, (cur) => { if (myChart) { /** * Clear the last data before drawing the chart here. Otherwise, data residues sometimes occur. */ (); (cur); } }, ); </script> <style scoped> .chart-container { position: relative; width: 100%; } .chart-loading { align-items: center; background-color: #ffffff; bottom: 0; display: flex; justify-content: center; left: 0; position: absolute; right: 0; top: 0; z-index: 1999; } .chart-empty { position: absolute; z-index: 1; left: 0; right: 0; top: 0; bottom: 0; color: #888; font-size: 14px; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; flex-direction: column; } .empty-title { font-size: 16px; font-weight: 500; color: #000; } </style>
- Component call
/** * Include corresponding parameters and chart configuration items */ <anewCharts :loading="loading" :data-empty-flag="dataEmptyFlag" :containerStyle="chartStyle" :options="chartOptions"></anewCharts>
Summarize
The above is personal experience. I hope you can give you a reference and I hope you can support me more.