echarts 組件復用
在前端開發過程中經常會遇到使用 echarts 報表的功能,有很多時候在一個頁面或者是一個項目當中使用相同的 echarts 表,比如使用好幾個柱狀圖、折線圖之類的,而這些柱狀圖的樣式是完全一樣的,只是橫縱坐標的數據不一樣,因此我們可以將樣式相同的 echarts 圖表封裝成一個組件,然后在需要使用的時候直接調用組件,傳入x軸、y軸數據或者是其他的標題之類的數據就可以使用,不需要每個圖表都單獨創建一個組件去調用,從而減少代碼量,提高組件復用性。
創建一個 bar 組件封裝 echarts 報表
<template>
<div style="width: 100%;height: calc(100% - 25px);">
<div id="top" style="width: 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",
width: 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="width: 100%;height: calc(100% - 25px);">
<!-- 假設有三個位置 top center bottom 需要渲染這個組件,需要創建三個div來渲染圖表
判斷通過傳進的id值,來判斷渲染哪一個div -->
<div id="top" style="width: 100%;height:100%;" v-if="id==='top'"></div>
<div id="center" style="width: 100%; height: 100%;" v-if="id==='center'"></div>
<div id="bottom" style="width: 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",
width: 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 ....
好了,可以點贊、關注、加評論了~ 哈哈哈哈!