【Echarts】如何封装一个简易通用的echarts组件【resize自适应/X轴和标题自定义点击事件/图表随接口实时更新/防内存泄漏】
如何封装一个简易的echarts组件
要求实现功能
- echarts图表要能自适应大小,并且能够岁窗口自适应resize
- 大屏首页有很echarts图标且要不停切换,需防止内存泄漏
- 接口定时刷新返回数据时,需要自动更新echarts
- 需要绑定自定义的echarts图表的X轴和标题的点击事件
2023.1.14
PS:当涉及到页面需要切换显示多个echarts,vue里需使用v-if进行切换而不是v-show,否则会出现加载时图表缩成一团的bug
2023.3.27
PS:flex布局下echarts的缩放会出现问题,例如出现在一行多列的弹性盒中,需要单独给flex-item子项设置一个最小宽度或高度
2023.6.21
PS:【Echarts】图表大屏自适应的升级解决方案,请滑到底部
以下是实现的核心代码,由于此次大屏项目中各个图形各异,考虑此处过分封装会导致耦合度过高,故没有对配置项option进行封装。
<template>
<div ref="myChart" :class="className" :style="{ height: height, width: width }" :option="option"/>
</template>
<script>
import * as echarts from "echarts";
// 缩放作防抖
import { debounce } from "@/utils";
export default {
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "100%",
},
// 图标样式和数据
option: {
type: Object,
required: true,
default: () => ({}),
},
},
data() {
return {
chart: null,
};
},
mounted() {
// 生成echart实例
this.initChart();
// 给窗口缩放resize加防抖
this.__resizeHandler = debounce(() => {
if (this.chart) this.chart.resize()
}, 500);
// 绑定窗口缩放resize事件
window.addEventListener("resize", this.__resizeHandler);
// * 绑定echarts X轴,标题的点击事件(当X轴或者标题是动态生成时,绑定在mounted无效)
// this.chart.on('click','xAxis',this.getDepartmentByxAxis)
// this.chart.on('click','title',this.getDepartmentByTitle)
},
beforeDestroy() {
// 销毁echart,防止内存泄露
if (!this.chart) return;
window.removeEventListener("resize", this.__resizeHandler);
this.chart.off('click')
this.$off()
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (this.chart !== null) this.chart.dispose();
this.chart = echarts.init(this.$refs.myChart);
// 因为有时候X轴是动态生成的,所以当绑定事件必须写在这里,否在单击未绑定在相应的位置
this.chart.on('click','xAxis',this.getDepartmentByxAxis)
this.chart.on('click','title',this.getDepartmentByTitle)
this.chart.setOption(this.option,true); //设置为true时不会合并数据,而是重新刷新数据
},
getDepartmentByxAxis(params){
this.$emit('departmentByAxis',params.value) // 通过X坐标,通知父组件部门的名字
},
getDepartmentByTitle(params){
this.$emit('departmenByTitle',params?.event?.target?.style?.text) // 通过title,通知父组件部门的名字
}
},
watch:{
option:{
deep:true,
handler(){
this.initChart()
}
}
}
};
</script>
【Echarts】图表大屏自适应的升级解决方案
洗尽铅华始见金,褪去浮华归本真