1.下载echarts
下载 yarn add echarts vue-echarts
进行下载
2.进行ts+vue3类型封装
封装目的:
在每次使用echarts时不再需要每次进行引入,但是保留option的自主权,data按照echarts指定格式传参即可。
进行封装:
将echarts进行按需引入
import { ref, watchEffect, onMounted, onUnmounted } from 'vue';
import * as echarts from 'echarts/core';
import { EChartsOption } from 'echarts/types/dist/shared';
import {
TooltipComponent,
LegendComponent,
TitleComponent,
GridComponent
} from 'echarts/components';
import { PieChart, BarChart, LineChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
echarts.use([
PieChart,
BarChart,
LineChart,
TooltipComponent,
LegendComponent,
CanvasRenderer,
TitleComponent,
GridComponent
]);
可以做成自动化引入,比如由父组件决定引入哪种图表,但是此项目仅仅是使用echarts的基本功能,不做此自动化引入
ts类型传参:
interface EchartProps {
chartOptions: EChartsOption;
chartType?: string;
chartHeight?: string;
chartWidth?: string;
chartData?: any;
xAxisData?: any;
xAxisType?: any;
}
const props: EchartProps = defineProps({
// 传递宽度
chartWidth: {
type: String,
default: '100%'
},
// 传递高度
chartHeight: {
type: String,
default: '400px'
},
// 传递数据
chartData: {
type: Array,
default: []
},
// 传递配置
chartOptions: {
type: Object,
default: () => ({})
},
// 传递图表类型
chartType: {
type: String,
default: 'pie'
},
// 传递x轴数据
xAxisData: {
type: Array,
default: () => []
},
xAxisType: {
type: String,
default: 'category'
}
});
这里传入的类型都由 EchartsProps
进行约束。
初始化实例:
const chart = ref<HTMLElement | null>(null);
const pieOption = ref();
// 初始化图表
const createChart = () => {
// 如果没有传递数据则不渲染图表
if (!chart.value) return;
// 初始化图表
const instance = echarts.init(chart.value);
// 设置图表配置
instance.setOption(generateOptions());
// 监听窗口大小变化
window.onresize = function () {
instance.resize();
};
};
这里需要注意的点是向Echarts推送父组件的值,此处不能直接将data和option一起使用setOption,如果出现没有data的情况,多半是这里出现问题。
销毁实例:
// 销毁图表
const destroyChart = () => {
if (!chart.value) return;
const instance = echarts.getInstanceByDom(chart.value);
if (instance) {
instance.dispose();
}
};
每次关闭页面时进行销毁实例。释放内存
添加effectWatch,监听每次数据变化时,echarts进行变化
// 监听数据变化,重新渲染图表
watchEffect(() => {
// 如果没有传递数据则不渲染图表
if (!chart.value) return;
// 获取图表实例
const instance = echarts.getInstanceByDom(chart.value as HTMLElement);
if (instance) {
// 重新渲染图表
instance.setOption(generateOptions());
}
});
如果仔细看的话会发现在初始化和监听数据变化的时候会触发一个generateOptions
的函数,此函数是针对数据进行配置
// 生成图表配置
const generateOptions = () => {
// 默认配置
let options: EChartsOption = {};
// 根据图表类型生成配置
switch (props.chartType) {
case 'bar':
// 合并配置
options = {
...props.chartOptions,
// 设置x轴数据
xAxis: {
type: props.xAxisType,
data: props.xAxisData,
...(props.chartOptions.xAxis || {})
},
// 设置图表类型,数据展示
series: [
{
type: 'bar',
data: props.chartData,
...((props.chartOptions.series as object) || {})
}
]
};
break;
case 'line':
options = {
...props.chartOptions,
// 设置x轴数据
xAxis: {
type: 'category',
data: props.xAxisData
},
// 设置图表类型,数据展示
series: [
{
type: 'line',
data: props.chartData,
...((props.chartOptions.series as object) || {})
}
]
};
break;
case 'pie':
default:
options = {
...props.chartOptions,
series: [
{
type: 'pie',
data: props.chartData,
...((props.chartOptions.series as object) || {})
}
]
};
pieOption.value = options;
break;
}
return options;
};
需要注意的是为了满足需求,在父组件传递配置的时候需要将series更改为
series: {
name: 'Access From',
type: 'pie',
radius: '50%',
avoidLabelOverlap: false,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
labelLine: {
show: false
},
label: {
show: false,
position: 'center'
}
}
在echarts中的格式是serise=[{}]
的格式,但是我们进行了解构赋值,所以更改一下格式。如果有特殊需求可以视情况更改
调用的格式为
<echarts
:chartData="chartBarData"
:chartOptions="chartBarOptions"
:chartWidth="'100%'"
:xAxisData="xAxisBarData"
:chartType="'bar'"
></echarts>
全部代码为:
<template>
<div
ref="chart"
:style="{ width: props.chartWidth, height: props.chartHeight }"
v-if="props.chartData"
></div>
</template>
<script setup lang="ts">
import { ref, watchEffect, onMounted, onUnmounted } from 'vue';
import * as echarts from 'echarts/core';
import { EChartsOption } from 'echarts/types/dist/shared';
import {
TooltipComponent,
LegendComponent,
TitleComponent,
GridComponent
} from 'echarts/components';
import { PieChart, BarChart, LineChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
echarts.use([
PieChart,
BarChart,
LineChart,
TooltipComponent,
LegendComponent,
CanvasRenderer,
TitleComponent,
GridComponent
]);
interface EchartProps {
chartOptions: EChartsOption;
chartType?: string;
chartHeight?: string;
chartWidth?: string;
chartData?: any;
xAxisData?: any;
xAxisType?: any;
}
const props: EchartProps = defineProps({
// 传递宽度
chartWidth: {
type: String,
default: '100%'
},
// 传递高度
chartHeight: {
type: String,
default: '400px'
},
// 传递数据
chartData: {
type: Array,
default: []
},
// 传递配置
chartOptions: {
type: Object,
default: () => ({})
},
// 传递图表类型
chartType: {
type: String,
default: 'pie'
},
// 传递x轴数据
xAxisData: {
type: Array,
default: () => []
},
xAxisType: {
type: String,
default: 'category'
}
});
const chart = ref<HTMLElement | null>(null);
const pieOption = ref();
// 初始化图表
const createChart = () => {
// 如果没有传递数据则不渲染图表
if (!chart.value) return;
// 初始化图表
const instance = echarts.init(chart.value);
// 设置图表配置
instance.setOption(generateOptions());
// 监听窗口大小变化
window.onresize = function () {
instance.resize();
};
};
// 销毁图表
const destroyChart = () => {
if (!chart.value) return;
const instance = echarts.getInstanceByDom(chart.value);
if (instance) {
instance.dispose();
}
};
// 生成图表配置
const generateOptions = () => {
// 默认配置
let options: EChartsOption = {};
// 根据图表类型生成配置
switch (props.chartType) {
case 'bar':
// 合并配置
options = {
...props.chartOptions,
// 设置x轴数据
xAxis: {
type: props.xAxisType,
data: props.xAxisData,
...(props.chartOptions.xAxis || {})
},
// 设置图表类型,数据展示
series: [
{
type: 'bar',
data: props.chartData,
...((props.chartOptions.series as object) || {})
}
]
};
break;
case 'line':
options = {
...props.chartOptions,
// 设置x轴数据
xAxis: {
type: 'category',
data: props.xAxisData
},
// 设置图表类型,数据展示
series: [
{
type: 'line',
data: props.chartData,
...((props.chartOptions.series as object) || {})
}
]
};
break;
case 'pie':
default:
options = {
...props.chartOptions,
series: [
{
type: 'pie',
data: props.chartData,
...((props.chartOptions.series as object) || {})
}
]
};
pieOption.value = options;
break;
}
return options;
};
// 监听数据变化,重新渲染图表
watchEffect(() => {
// 如果没有传递数据则不渲染图表
if (!chart.value) return;
// 获取图表实例
const instance = echarts.getInstanceByDom(chart.value as HTMLElement);
if (instance) {
// 重新渲染图表
instance.setOption(generateOptions());
}
});
onMounted(() => {
createChart();
});
onUnmounted(() => {
destroyChart();
});
</script>
<style scoped>
.echarts-chart {
width: 100%;
height: 100%;
}
</style>
总结:此次封装仅仅为初步封装,暂时没有考虑更多的情况,但是针对基本情况是够用的。并且灵活度很高,并没有进行二次封装。针对折线图,柱状图和饼状图都可以直接调用。