寫在前面
最近好長時間一直在做可視化項目,我采用的是echarts可視化圖表工具畫圖,一開始由于時間的倉促写妥,還有沒有去研究鸳粉,各方面原因吧,以前每次做圖表之類的都沒有封裝集畅,每次做圖表都要從新去配置之類的近弟,寫了好多重復代碼,感覺很累啊挺智,所以自己把圖表封裝成子組件使用祷愉,代碼工作量減輕了很多,而且子組件使用了數(shù)據(jù)進行監(jiān)聽和圖表自適應屏幕大小赦颇,這樣以后會方便很多了二鳄!簡直帥到爆,不多說了媒怯,上思路和代碼订讼。
我用的是vue-cli全家桶+echarts,做的封裝扇苞,先將代碼貼出來欺殿,以便于學習以及幫助到小伙伴
首先用的腳手架需要先安裝echarts,然后全局引入
npm install echarts --save
全局引入,main.js里邊配置
// 引入echarts
import echarts from 'echarts'
Vue.prototype.$echarts = echarts
這樣在每個頁面就可以使用了
之前一開始都是每個頁面配置鳖敷,現(xiàn)在將其封裝好山宾,方便開發(fā)以及維護。下邊為思路以及代碼
StepOne: 在項目的components下新建一個文件夾Echarts,在其下邊新建一個index.vue,里邊存放公共的echarts組件鳍徽。里邊的注釋我已經(jīng)寫的很全面了资锰,還有不理解的評論。原理就是正常的父子組件傳值阶祭。
由于Echarts/index.vue子組件在初始化就會加載绷杜,后期不會更新,再加上由于echarts采用的數(shù)據(jù)驅動濒募,所以需要監(jiān)聽數(shù)據(jù)的變化來重繪圖表
<template>
每一個圖表都有自己唯一的id,所有需要動態(tài)傳入鞭盟。
<div class="echartsLine"
:id="id"
:style="style"></div>
</template>
<script>
export default {
props: {
id: {
type: String
},
width: {
type: String,
default: "100%"
},
height: {
type: String
},
option: {
type: Object
}
},
data() {
return {
MyEcharts: "" //echarts實例
};
},
computed: {
style() {
return {
height: this.height,
width: this.width
};
}
},
watch: {
//要監(jiān)聽的對象 option
//由于echarts采用的數(shù)據(jù)驅動,所以需要監(jiān)聽數(shù)據(jù)的變化來重繪圖表
option: {
handler(newVal, oldVal) {
if (this.MyEcharts) {
if (newVal) {
console.log(newVal);
第一種方法:
this.MyEcharts.setOption(newVal, true);
第二種方法:
let publicCharts = this.MyEchartsOption(newVal);
console.log(publicCharts);
this.MyEcharts.setOption(publicCharts, true);
} else {
第一種方法:
this.MyEcharts.setOption(oldVal, true);
第二種方法:
let publicCharts = this.MyEchartsOption(oldVal);
this.MyEcharts.setOption(publicCharts, true);
}
} else {
this.InitCharts();
}
},
deep: true //對象內部屬性的監(jiān)聽瑰剃,關鍵齿诉。
}
},
mounted() {
this.InitCharts();
},
methods: {
//所設計的圖表公共組件,不論第一種方法還是第二種方法都按照官網(wǎng)的格式來寫數(shù)據(jù)晌姚,這樣方便維護
InitCharts() {
this.MyEcharts = this.$echarts.init(document.getElementById(this.id));
/**
* Author HaoYanFeng
* 第一種
* 此方法適用于所有項目的圖表粤剧,但是每個配置都需要在父組件傳進來,相當于每個圖表的配置都需要寫一遍挥唠,不是特別的省代碼抵恋,主要是靈活度高
* echarts的配置項,你可以直接在外邊配置好宝磨,直接扔進來一個this.option
*/
this.MyEcharts.clear(); //適用于大數(shù)據(jù)量的切換時圖表繪制錯誤,先清空在重繪
this.MyEcharts.setOption(this.option, true); //設置為true可以是圖表切換數(shù)據(jù)時重新渲染
/**
* Author HaoYanFeng
* 第二種
* 此方法不適用于所有項目弧关,只適用于本項目,但是可以省好多代碼唤锉,維護性高
* 在這你還可以根據(jù)需求將你的配置項中公共的提取出來世囊,這樣就可以省很多代碼
*/
console.log(this.option);
if (this.option.tooltip != undefined) {
let publicCharts = this.MyEchartsOption(this.option);
console.log(publicCharts);
this.MyEcharts.clear(); //適用于大數(shù)據(jù)量的切換時圖表繪制錯誤,先清空在重繪
this.MyEcharts.setOption(publicCharts, true); //設置為true可以是圖表切換數(shù)據(jù)時重新渲染
}
以下這種方法,當一個頁面有多個圖表時腌紧,會有一個bug那就是只有一個圖表會隨著窗口大小變化而變化茸习,經(jīng)過小編的努力,終于找到解決辦法壁肋。
window.onresize = () => {
this.MyEcharts.resize();
}; //當窗口變化時隨瀏覽器大小而改變
以下為上邊的bug的解決方案号胚。以后用這種方案,放棄上一種浸遗。
let _this = this;
window.addEventListener("resize", function() {
_this.MyEcharts.resize();
});
},
/**
* Author HaoYanFeng
* 第二種 公共的配置猫胁,省代碼
* 此方法不適用于所有項目,只適用于本項目跛锌,但是可以省好多代碼弃秆,維護性高
* 在這你還可以根據(jù)需求將你的配置項中公共的提取出來届惋,這樣就可以省很多代碼
*/
MyEchartsOption(configures) {
if (configures.tooltip != undefined) {
let MyOption = {
//圖標的標題 本項目暫未使用
title: {
// text: configures.title.text
},
//鼠標懸浮提示框
tooltip: {
trigger: "axis",
confine: true, //是否將 tooltip 框限制在圖表的區(qū)域內。 true為是
axisPointer: {
// 坐標軸指示器菠赚,坐標軸觸發(fā)有效
type: configures.tooltip.axisPointer.type // 默認為直線脑豹,可選為:'line' | 'shadow'
},
formatter: configures.tooltip.formatter
},
//圖例
legend: {
//圖例的數(shù)據(jù)數(shù)組
// data: configures.legend.data, //圖例的數(shù)據(jù)數(shù)組 一般不設置,自動根據(jù)數(shù)據(jù)匹配
top: configures.legend.top, //圖例組件離容器上側的距離
right: configures.legend.right, //圖例組件離容器右側的距離
bottom: configures.legend.bottom, //圖例組件離容器下側的距離
left: configures.legend.left, //圖例組件離容器左側的距離
textStyle: {
color: this.echartsXYcolor //在本項目中涉及到主題色切換衡查,所以采用動態(tài)顏色瘩欺,黑白兩色,下邊相同
}
},
//工具欄拌牲。內置有導出圖片俱饿,數(shù)據(jù)視圖,動態(tài)類型切換塌忽,數(shù)據(jù)區(qū)域縮放拍埠,重置五個工具。
// toolbox: {
// feature: {
// saveAsImage: {}
// }
// },
//直角坐標系內繪圖網(wǎng)格
grid: {
top: configures.grid.top, //grid 組件離容器上側的距離土居。也就是圖表距離容器
//在本項目中每個圖表都是距左右下100px枣购,這樣的話就有一個缺點不靈活,但是適用于本項目擦耀,不需要每一個都修改坷虑,若要做靈活了就是如top寫法,每個圖表都要配置
left: "100px",
right: "100px",
bottom: "100px"
},
//x軸的數(shù)據(jù)以及配置
xAxis: {
type: configures.xAxis.type, //坐標軸類型埂奈。具體參考官方文檔
boundaryGap: configures.xAxis.boundaryGap, //類目軸中 boundaryGap 可以配置為 true 和 false。默認為 true定躏,這時候刻度只是作為分隔線账磺,標簽和數(shù)據(jù)點都會在兩個刻度之間的帶(band)中間。
data: configures.xAxis.data, //x軸的數(shù)據(jù)
axisLine: {
lineStyle: {
color: this.echartsXYcolor
}
},
axisLabel: {
textStyle: {
color: this.echartsXYcolor
}
}
},
//y軸的數(shù)據(jù)配置
yAxis: {
axisLine: {
lineStyle: {
color: this.echartsXYcolor
}
},
axisLabel: {
textStyle: {
color: this.echartsXYcolor
},
formatter: configures.yAxis.axisLabel.formatter
}
},
// dataZoom 組件 用于區(qū)域縮放痊远,從而能自由關注細節(jié)的數(shù)據(jù)信息垮抗,或者概覽數(shù)據(jù)整體,或者去除離群點的影響碧聪。
dataZoom: [
{
type: "inside"
},
{
type: "slider",
top: configures.dataZoom[1].top, //距離容器上邊的距離
textStyle: {
color: this.echartsXYcolor
}
}
],
//圖表的數(shù)據(jù)
series: configures.series //由于數(shù)據(jù)的靈活度大冒版,所以完全采用傳入的方式
};
return MyOption;
}
}
}
};
</script>
<style lang="scss" scoped>
</style>
StepTwo:在使用頁面例如有一個mycharts.vue文件,引用直接引入并傳值就好了逞姿。
<template>
<!-- 業(yè)績表現(xiàn) -->
<div class="index">
<MyEcharts :id="'exampleId'"
:style="{width: '100%', height: '380px'}"
:option="chartOption">
</MyEcharts>
</div>
</template>
import MyEcharts from "@/components/Echarts/index"; //echarts
export default {
components: {
MyEcharts
},
data() {
return {
chartOption: {},
echartsXYcolor:"#fff000",
lineColor:"#5bb1f0"
}
},
mounted(){
this.initCharts();
},
methods:{
initCharts(){
this.chartOption = {
title: {
text: '折線圖'
},
tooltip: {
trigger: "axis",
confine: true, //是否將 tooltip 框限制在圖表的區(qū)域內辞嗡。 true為是
axisPointer: {
// 坐標軸指示器,坐標軸觸發(fā)有效
type: "line" // 默認為直線滞造,可選為:'line' | 'shadow'
},
formatter: function(params) {
return params;
}
},
legend: {
data:[],
top: "93%",
right:'center',
bottom:"center",
left:"center",
textStyle: {
color: this.echartsXYcolor
}
},
// toolbox: {
// feature: {
// saveAsImage: {}
// }
// },
grid: {
top: "3%",
left: "100px",
right: "100px",
bottom: "100px"
},
xAxis: {
type: "category",
boundaryGap: false,
data: data: ['周一','周二','周三','周四','周五','周六','周日'],
axisLine: {
lineStyle: {
color: this.echartsXYcolor
}
},
axisLabel: {
textStyle: {
color: this.echartsXYcolor
}
}
},
dataZoom: [
{
type: "inside"
},
{
type: "slider",
top: "82%",
textStyle: {
color: this.echartsXYcolor
}
}
],
yAxis: {
axisLine: {
lineStyle: {
color: this.echartsXYcolor
}
},
axisLabel: {
textStyle: {
color: this.echartsXYcolor
},
formatter: function(val) {
return (val * 1).toFixed(2) + "%";
}
}
},
series: [
{
name: '郵件營銷',
type: "line",
lineStyle: {
color: this.lineColor // 線的顏色
},
itemStyle: {
color: this.lineColor// 圖例的顏色
},
showSymbol: false, // 不顯示symbol
data:[120, 132, 101, 134, 90, 230, 210]
}
]
};
}
}
}
結束語
至此续室,一個完整的封裝好的公共的vue-echarts組件就完工了,可以在項目中直接調用谒养,里邊都有公共的配置項挺狰,以及父組件完全傳入配置兩種方案,各有利弊,還有重繪丰泊,以及隨瀏覽器大小而改變大小薯定。希望簡友可以提寶貴的意見在評論區(qū)評論。