echarts 组件复用
在前端开发过程中经常会遇到使用 echarts 报表的功能,有很多时候在一个页面或者是一个项目当中使用相同的 echarts 表,比如使用好几个柱状图、折线图之类的,而这些柱状图的样式是完全一样的,只是横纵坐标的数据不一样,因此我们可以将样式相同的 echarts 图表封装成一个组件,然后在需要使用的时候直接调用组件,传入x轴、y轴数据或者是其他的标题之类的数据就可以使用,不需要每个图表都单独创建一个组件去调用,从而减少代码量,提高组件复用性。
创建一个 bar 组件封装 echarts 报表
<template>
<div style=" 100%;height: calc(100% - 25px);">
<div id="top" style=" 100%;height:100%;"></div>
</div>
</template>
<script>
import echarts from 'echarts'
// 引入改变窗口重新加载图表js。这个文件看之前的博客,有使用介绍
import { EleResize } from '../../../../../../public/js/esresize.js'
import 'echarts-gl'
export default {
name: '',
props: ['showData'],
data() {
return {
charts: '',
}
},
watch: {
showData() {
this.$nextTick(function () {
this.drawMap('top')
})
}
},
created() {
this.$nextTick(function () {
this.drawMap('top')
})
},
methods: {
drawMap(id) {
let option = {
color: ['#3398DB'],
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
grid: {
left: '3%',
right: '3%',
bottom: '0%',
top: '10%',
containLabel: true
},
xAxis: [
{
type: 'category',
boundaryGap: true,
data: this.showData.xValue,
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: "#9e9fa3",
0,
},
},
}
],
yAxis: [
{
type: 'value',
axisLabel: {
margin: 15,
formatter: "{value}",
textStyle: {
color: "#9e9fa3",
},
},
axisTick: {
show: false
},
splitLine: {
lineStyle: {
color: "#c8c9cb",
type: "dashed"
},
},
axisLine: {
show: false,
lineStyle: {
color: "#9e9fa3",
},
},
}
],
series: [
{
name: '数据',
type: 'bar',
barWidth: '50%',
data: this.showData.yValue
}
]
};
this.charts = echarts.init(document.getElementById(id))
// 改变屏幕大小图表重新加载
var resizeDiv = document.getElementById(id)
var listener = () => {
this.charts.resize()
}
EleResize.on(resizeDiv, listener)
this.charts.clear()
this.charts.setOption(option)
}
},
// 调用
mounted() { },
// 销毁
destroyed() {
// 销毁echarts图表
this.charts.dispose()
}
}
</script>
如果单独每个echarts图表写一个vue组件按照上面就可以了。
showData是一个对象,里面有两个列表,xValue 是 x 轴数据,yValue 是 y 轴数据,然后放到相应的地方渲染就可以了。
留坑
但是这个组件是不可以复用的,如果有一个和这个图表样式相同的报表,再次调用传进 showData 数据会发现渲染不对,出问题,为什么,因为 echarts 渲染的时候,需要先创建一个 div 标签设置长宽渲染 echarts 图表,但是有一个问题,渲染的时候需要这个 div 有一个唯一的 id 值,这样的话,如果两个图表调用这同一个封装好的组件会有两个 id 相同的 div,因此会出现渲染问题。
填坑
这样的话,就需要在每次调用组件的时候,需要设置一个唯一 id 的 div 来渲染不同位置的 echarts 图表。
修改之前的代码:
<template>
<div style=" 100%;height: calc(100% - 25px);">
<!-- 假设有三个位置 top center bottom 需要渲染这个组件,需要创建三个div来渲染图表
判断通过传进的id值,来判断渲染哪一个div -->
<div id="top" style=" 100%;height:100%;" v-if="id==='top'"></div>
<div id="center" style=" 100%; height: 100%;" v-if="id==='center'"></div>
<div id="bottom" style=" 100%; height: 100%;" v-if="id==='bottom'"></div>
</div>
</template>
<script>
import echarts from 'echarts'
// 引入改变窗口重新加载图表js
import { EleResize } from '../../../../../../public/js/esresize.js'
import 'echarts-gl'
export default {
name: '',
props: ['showData', 'id', 'unit'], // showData是xy轴数据,id是div id值,unit是单位
data() {
return {
charts: '',
}
},
watch: {
showData() {
this.$nextTick(function () {
switch (this.id) {
case 'top':
this.drawMap('top')
break;
case 'center':
this.drawMap('center')
break;
case 'bottom':
this.drawMap('bottom')
break;
}
})
}
},
created() {
this.$nextTick(function () {
switch (this.id) {
case 'top':
this.drawMap('top')
break;
case 'center':
this.drawMap('center')
break;
case 'bottom':
this.drawMap('bottom')
break;
}
})
},
methods: {
drawMap(id) {
let option = {
color: ['#3398DB'],
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
grid: {
left: '3%',
right: '3%',
bottom: '0%',
top: '10%',
containLabel: true
},
xAxis: [
{
type: 'category',
boundaryGap: true,
data: this.showData.xValue,
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: "#9e9fa3",
0,
},
},
}
],
yAxis: [
{
type: 'value',
axisLabel: {
margin: 15,
formatter: "{value}",
textStyle: {
color: "#9e9fa3",
},
},
axisTick: {
show: false
},
splitLine: {
lineStyle: {
color: "#c8c9cb",
type: "dashed"
},
},
axisLine: {
show: false,
lineStyle: {
color: "#9e9fa3",
},
},
}
],
series: [
{
name: this.unit,
type: 'bar',
barWidth: '50%',
data: this.showData.yValue
}
]
};
this.charts = echarts.init(document.getElementById(id))
// 改变屏幕大小图表重新加载
var resizeDiv = document.getElementById(id)
var listener = () => {
this.charts.resize()
}
EleResize.on(resizeDiv, listener)
this.charts.clear()
this.charts.setOption(option)
}
},
// 调用
mounted() { },
// 销毁
destroyed() {
// 销毁echarts图表
this.charts.dispose()
}
}
</script>
<style scoped>
* {
margin: 0;
padding: 0;
list-style: none;
}
</style>
这样的话就可以在三个地方渲染这样的这个组件,但是如果有新位置也需要在加 div,也比每个图表创建一个 Vue 文件要方便许多,而且需要修改样式就可以修改这一个文件就可以了,不需要一个一个修改。
然后调用的时候:
<echart-bar :id="'center'" :showData="barCenter" :unit="'占比'"></echart-bar>
<echart-bar :id="'bottom'" :showData="bottomCenter" :unit="'数量'"></echart-bar>
图就暂时不截了...
优化
其实还有一个简单的方法,一直没说,因为上面基本上说的就是原理之类的解决方法,如果理解上面的骚操作,优化的方法不说估计也能想到。
提示: 传进来的 id 直接赋值给 div 的 id ,就不需要每次创建 div 设置唯一的 id 了 。
还有别的办法,ref ....
好了,可以点赞、关注、加评论了~ 哈哈哈哈!