背景
echarts是一种数据可视化方案,通过图形可以直观,简洁的呈现我们要展示的数据,是我们数据可视化中开发中必不可少的一种方案,相信大家都有用过这个东西,也有一些自己的开发方案,现在我想跟大家介绍一下我的封装方案,希望可以跟大家一起讨论进步一下。 我的封装解决了以下几个问题
- 解决不断去写初始化echarts实例的代码
- 解决父元素从隐藏到展示后,echarts只有100px宽高的问题
- 解决窗口变化后,echarts不能自适应问题
- 只处理options相关代码,可以允许使用者在基础上,封装项目中特有的,共同的echart的实现
1.安装包
yarn add echarts -S // 安装echarts包
yarn add resize-observer-polyfill -S // 基于 MutationObserver 实现的一个可以观察窗口(div元素)宽高变化的包
2.代码封装
<script lang="ts">
/* @description
* @fileName EchartRender.vue
* @author maqianbo-web
* @date 2023/10/07 10:35:39
* @version
*/
export default {
name: 'EchartRender',
};
</script>
<script setup lang="ts">
import { ref, onMounted, nextTick, watch } from 'vue';
import * as echarts from 'echarts';
import { ECharts } from 'echarts';
import ResizeObserver from 'resize-observer-polyfill';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const prop = defineProps<{ echartOptions: any }>();
const emit = defineEmits<{
(e: 'instance', value: ECharts): void;
(e: 'click', value: echarts.ECElementEvent): void;
}>();
const echartWrap = ref<HTMLElement | null>(null);
let echartInstance: ECharts | null = null;
let resizeObserver: ResizeObserver | null = null;
onMounted(() => {
initRender();
});
watch(
prop.echartOptions,
() => {
renderEchart();
},
{ deep: true }
);
const initRender = () => {
nextTick(() => {
if (!echartInstance) {
echartInstance = echarts.init(echartWrap.value);
}
resizeObserver = new ResizeObserver(() => {
window.requestAnimationFrame(() => {
echartInstance?.resize(); // 窗口宽高变化,可以重新渲染echarts(可解决打开模态框echarts只有100px问题)
});
});
resizeObserver.observe(echartWrap.value as HTMLElement);
echartInstance.on('click', (params: echarts.ECElementEvent) => {
emit('click', params);
});
emit('instance', echartInstance);
renderEchart();
});
};
const renderEchart = () => {
echartInstance?.clear();
echartInstance?.setOption(prop.echartOptions);
};
onMounted(() => {
echartInstance?.dispose();
resizeObserver?.unobserve(echartWrap.value as HTMLElement);
});
</script>
<template>
<section ref="echartWrap" class="h-full flex-center"></section>
</template>
<style lang="less" scoped></style>
3.使用
<script lang="ts">
export default {
name: 'EchartShow',
};
</script>
<script setup lang="ts">
import { onMounted, reactive } from 'vue';
import { EChartsOption } from 'echarts';
import EchartRender from './components/EchartRender.vue';
const getBarOptions: (name: string) => EChartsOption = (name) => {
return {
tooltip: {},
legend: {
data: [name],
},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
},
yAxis: {},
series: [
{
name,
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
},
],
};
};
const getLineOptions = () => {
return {
tooltip: {},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line',
},
],
};
};
let data = reactive({
barOptions: {},
lineOptions: {},
});
onMounted(() => {
// 可以将一些经常用的,相同的options生成方案提炼出来,使用
let barOptions = getBarOptions('销售');
data.barOptions = reactive(barOptions);
let lineOptions = getLineOptions();
data.lineOptions = lineOptions;
});
</script>
<template>
<el-row class="wrap">
<el-col :span="12">
<echart-render :echart-options="data.barOptions"></echart-render>
</el-col>
<el-col :span="12">
<echart-render :echart-options="data.lineOptions"></echart-render>
</el-col>
</el-row>
</template>
<style lang="less" scoped>
.wrap {
height: 300px;
}
</style>
代码仓库
github.com/maqianbo-we… 需要查看的小伙伴可以自己克隆下来试一下