引言
開發(fā)前端項目過程中蚕捉,有大量的圖表數據需要展示律胀,為了更方便地使用以及代碼的復用,于是基于ECharts封裝了各種各樣的圖表組件情连。直接使用封裝好的組件對于剛接觸我們項目的人來說會比較友好叽粹,而理解組件的封裝思路和封裝細節(jié),將會有助于我們更加嫻熟地運用組件到實踐中却舀。本文將會以雷達圖為案例虫几,一步步講解在vue項目中如何使用echart,如何將其封裝為能重復調用的組件挽拔。
準備工作
在開始之前辆脸,我們先按照正常的組件注冊流程,在項目 components 目錄中新建一個名為 radar-chart 的組件螃诅,然后在一個 Demo 頁面引入該組件使用啡氢。
新建的 radar-chart 組件內容:
// radar-chart.vue (子組件)
<template>
<div style="width: 100%; height: 100%;"></div>
</template>
<script>
export default {
name: 'radar-chart'
};
</script>
<style scoped>
</style>
Demo 頁面代碼:
// demo.vue (父組件)
<template>
<div style="border: 1px solid black; width: 400px; height: 300px; margin: 5px;">
<radar-chart></radar-chart>
</div>
</template>
<script>
import radarChart from '@/components/proj-components/echarts/radar-chart';
export default {
name: 'radar-chart-demo',
components: {
radarChart,
},
};
</script>
<style scoped>
</style>
Demo 頁面效果圖一:
初始化圖表
準備工作完成之后,我們要做的是引入 ECharts术裸,并在組件中初始化一個 ECharts 的實例倘是,這里可以先照搬官網的實例和數據。
(1)在 radar-chart.vue 引入 ECharts :
// radar-chart.vue (子組件)
import echarts from 'echarts';
(2)在 methods 中創(chuàng)建圖表配置數據的方法袭艺,數據格式參考 Echarts 官網:
// radar-chart.vue (子組件)
methods: {
// 初始化圖表配置
initOption() {
let vm = this;
vm.option = {
title: {
text: '基礎雷達圖'
},
tooltip: {},
legend: {
data: ['預算分配(Allocated Budget)', '實際開銷(Actual Spending)']
},
radar: {
// shape: 'circle',
name: {
textStyle: {
color: '#fff',
backgroundColor: '#999',
borderRadius: 3,
padding: [3, 5]
}
},
indicator: [{ name: '銷售(sales)', max: 6500}, { name: '管理(Administration)', max: 16000}, { name: '信息技術(Information Techology)', max: 30000}, { name: '客服(Customer Support)', max: 38000}, { name: '研發(fā)(Development)', max: 52000}, { name: '市場(Marketing)', max: 25000}]
},
series: [{
name: '預算 vs 開銷(Budget vs spending)',
type: 'radar',
// areaStyle: {normal: {}},
data: [{value: [4300, 10000, 28000, 35000, 50000, 19000], name: '預算分配(Allocated Budget)'}, {value: [5000, 14000, 28000, 31000, 42000, 21000], name: '實際開銷(Actual Spending)'}]
}]
};
},
},
(3)初始化圖表:
在組件鉤子 mounted 方法中:
// radar-chart.vue (子組件)
mounted() {
this.initOption();
this.$nextTick(() => { // 這里的 $nextTick() 方法是為了在下次 DOM 更新循環(huán)結束之后執(zhí)行延遲回調搀崭。也就是延遲渲染圖表避免一些渲染問題
this.ready();
});
},
在 methods 中:
// radar-chart.vue (子組件)
ready() {
let vm = this;
let dom = document.getElementById('radar-chart');
vm.myChart = echarts.init(dom);
vm.myChart && vm.myChart.setOption(vm.option);
},
Demo 頁面效果圖二:
這里一共分了三步,引入 ECharts猾编、初始化圖表配置瘤睹、初始化圖表,最后可以在 Demo 頁面中看到答倡,已經初步地把 ECharts 的雷達圖顯示到項目中來了轰传。
提取圖表配置屬性(重點)
上面我們已經成功創(chuàng)建一個雷達圖了,但是很明顯的是瘪撇,radar-chart.vue 里的數據寫死的获茬,無法重復調用。接下來著手封裝的事情了设江。
封裝的思路是這樣的:
- demo.vue 向 radar-chart.vue 傳遞一組個性化數據
- radar-chart.vue 通過 props 選項接收數據
- 提煉接收到的數據锦茁,覆蓋配置數據 option
- 初始化圖表
具體實現:
向子組件傳遞數據,在 data 中定義變量叉存,在 mounted 中賦值
// demo.vue (父組件)
<template>
<div style="border: 1px solid black; width: 900px; height: 600px; margin: 5px;">
<radar-chart :indicator="indicator" :legendData="radarData"></radar-chart>
</div>
</template>
<script>
import radarChart from '@/components/proj-components/echarts/radar-chart';
export default {
name: 'radar-chart-demo',
components: {
radarChart,
},
mounted() {
this.indicator = [
{ name: '銷售', max: 6500 },
{ name: '管理', max: 16000 },
{ name: '信息技術', max: 30000 },
{ name: '客服', max: 38000 },
];
this.radarData = [
{
value: [4000, 15000, 26000, 21000],
name: '實際開銷(Actual Spending)',
}
];
},
data() {
return {
indicator: [], // 雷達指示器數據
legendData: [], // 雷達圖例數據
};
},
};
</script>
<style scoped>
</style>
在 props 中接收來自父組件的數據
// radar-chart.vue (子組件)
props: {
// 指示器數據码俩,必傳項
// 格式舉例 [{ name: 'a', max: 1},{ name: 'a', max: 1},{ name: 'a', max: 1}]
indicator: {
type: Array,
default: () => []
},
// 圖例數據,必填項歼捏。
// 格式舉例 [{ value: [5000, 14000, 28000], name: 'name' }稿存,{ value: [5000, 14000, 28000], name: 'name' }]
legendData: {
type: Array,
default: () => []
},
},
在 ready() 中更新圖表數據 option
如果在這里更新 indicator笨篷、data 這兩個屬性值,initOption() 中就不需要初始化這兩個值了
// radar-chart.vue (子組件)
ready() {
let vm = this;
let dom = document.getElementById('radar-chart');
vm.myChart = echarts.init(dom);
// 得到指示器數據
vm.option.radar.indicator = vm.indicator;
// 得到圖例數據
vm.option.series[0].data = vm.legendData;
vm.myChart && vm.myChart.setOption(vm.option);
},
Demo 頁面效果圖三:
細節(jié)優(yōu)化與其他注意事項
以下代碼均是基于已完成代碼的修改和添加
1.一個頁面有多個圖表的情況下瓣履,自動生成圖表 ID率翅。實現原理參考 ES6 模塊化和 .vue組件的應用舉例。補充代碼:
// radar-chart.vue (子組件)
<template>
<div :id="chartId" style="height: 100%; width: 100%;"></div>
</template>
<script>
let chartIdSeed = 1;
export default {
data() {
return {
chartId: 1,
};
},
mounted() {
let vm = this;
vm.chartId = 'radar-chart_' + chartIdSeed++;
},
methods: {
let vm = this;
let dom = document.getElementById(vm.chartId);
}
};
</script>
2.圖表數據屬性用 props 接收袖迎,圖表默認配置屬性用 defaultConfig 保存冕臭,父組件傳入的配置屬性 chartConfig 通過 $attrs 直接取得,最終合并為 finallyConfig 使用燕锥,利于擴展與維護辜贵。補充代碼:
// radar-chart.vue (子組件)
<script>
export default {
data() {
return {
// 默認配置項。以下配置項可以在父組件 :chartConfig 進行配置归形,會覆蓋這里的默認配置
defaultConfig: {
tooltipShow: true
},
finallyConfig: {}, // 最后配置項
};
},
mounted() {
// 在這里合并默認配置與父組件傳進來的配置
vm.finallyConfig = Object.assign({}, vm.defaultConfig, vm.$attrs.chartConfig);
},
methods: {
initOption() {
vm.option = {
tooltip: {
show: vm.finallyConfig.tooltipShow, // 在這里使用最終配置
},
}
},
}
};
</script>
3.使用 watch 監(jiān)聽圖表數據更新
// radar-chart.vue (子組件)
watch: {
legendData() {
this.$nextTick(() => {
this.ready();
});
}
},
4.添加窗口 resize 事件和圖表 click 事件
// radar-chart.vue (子組件)
export default {
data() {
return {
chartResizeTimer: null, // 定時器托慨,用于resize事件函數節(jié)流
};
},
methods: {
ready() {
// 添加窗口resize事件
window.addEventListener('resize', vm.handleChartResize);
// 觸發(fā)父組件的 @chartClick 事件
vm.myChart.on('click', function(param) {
vm.$emit('chartClick', param);
});
},
// 處理窗口resize事件
handleChartResize() {
let vm = this;
clearTimeout(vm.chartResizeTimer);
vm.chartResizeTimer = setTimeout(function() {
vm.myChart && vm.myChart.resize();
}, 200);
},
},
beforeDestroy() {
// 釋放該圖例資源,較少頁面卡頓情況
if (this.myChart) this.myChart.clear();
// 移除窗口resize事件
window.removeEventListener('resize', this.handleChartResize);
}
};