一、需求问题
在开发vue的项目中,我们可能会遇到这样的需求。我们需要去封装一个图表组件,然后这个图表组件在多个不同的页面中都是可以使用的。下面也就是我所封装的图表组件Chart,可以去实现复用。
二、需求分析
我们需要先引用echarts
,初始化图表,设置配置项,进行渲染,监视传入的option
参数,如果有变化则重新设置配置项,这样一个图表组件就已经封装好了。在其它页面当中,进行图表组件的引入。option
合并传入的数据,返回一个 echarts
的 配置项,在组件装载前进行数据的请求。
三、需求实现
1. 封装Chart图表组件
<template>
<div class="default-chart" :style="{width, height}"></div>
</template>
<script>
import * as echarts from 'echarts/lib/echarts';
import 'zrender/lib/svg/svg';
// 引入提示框和标题组件
import throttle from '../../utils/throttle';
export default {
name: 'basic-echarts',
props: { // 规范传入参数格式,以及默认值
renderer: {
type: String,
required: false
},
option: {
type: Object,
default: () => ({})
},
notMerge: {
type: Boolean,
default: false
},
lazyUpdate: {
type: Boolean,
default: false
}
},
data() {
return {
chart: null,
width: '100%',
height: '100%'
};
},
methods: {
// 初始化图表
initChart(el) {
// renderer 用于配置渲染方式 可以是 svg 或者 canvas
const renderer = this.renderer || 'canvas';
console.log(renderer);
this.chart = echarts.init(el, null, {
renderer,
width: 'auto',
height: 'auto'
});
},
// 设置配置项
setOption(option) {
if (!this.chart) {
return;
}
const notMerge = this.notMerge;
const lazyUpdate = this.lazyUpdate;
this.chart.setOption(option, notMerge, lazyUpdate);
},
// 销毁
dispose() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
// 重新渲染
resize() {
this.chart && this.chart.resize();
},
getInstance() {
return this.chart;
}
},
mounted() {
this.$nextTick(function() {
console.log('did mount');
this.initChart(this.$el);
this.setOption(this.option);
window.addEventListener('resize', throttle(this.resize, 100));
});
},
beforeDestroy() {
this.dispose();
},
watch: {
// 监视传入的 option 参数,如果有变化则重新设置配置项
option(newOpt) {
console.log('update config');
this.setOption(newOpt);
}
}
};
</script>
<style lang="scss" scoped>
@import '../../scss/_common.scss';
</style>
- 其它页面引用图表组件
<!-- ECharts -- Radar -- 雷达图 -->
<template>
<Chart :renderer="renderer" :option="option"/>
</template>
<script>
import { mapActions, mapState } from 'vuex';
// 引入当前图表配置需要用到的图表、组件
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/lib/component/grid';
import 'echarts/lib/component/legend';
import 'echarts/lib/chart/radar';
import 'echarts/map/js/china';
import Chart from '../components/Charts/index';
const colors = [
'#bcd3bb',
'#e88f70',
'#edc1a5',
'#9dc5c8',
'#e1e8c8',
'#7b7c68',
'#e5b5b5',
'#f0b489',
'#928ea8',
'#bda29a'
];
export default {
name: 'echarts-radar',
data() {
return { renderer: 'canvas' };
},
computed: {
...mapState('charts', { currentData: 'radar' }),
provinces() {
const currentData = this.currentData || [];
return currentData.map(data => data.province);
},
// option 合并传入的数据,返回一个 echarts 的 配置项
option() {
return {
backgroundColor: '#161627',
title: {
text: 'AQI - 雷达图',
left: 'center',
textStyle: {
color: '#eee'
}
},
legend: {
bottom: 5,
data: this.provinces,
itemGap: 20,
textStyle: {
color: '#fff',
fontSize: 14
},
selectedMode: 'single'
},
radar: {
indicator: [
// 雷达图指示器
{ name: 'AQI', max: 200 },
{ name: 'PM2.5', max: 250 },
{ name: 'PM10', max: 250 },
{ name: 'CO', max: 5 },
{ name: 'NO2', max: 150 },
{ name: 'SO2', max: 120 }
],
shape: 'circle', // 形状
splitNumber: 5, // 分割段数
splitLine: {
// 分隔线
lineStyle: {
color: [
'rgba(238, 197, 102, 0.1)',
'rgba(238, 197, 102, 0.2)',
'rgba(238, 197, 102, 0.4)',
'rgba(238, 197, 102, 0.6)',
'rgba(238, 197, 102, 0.8)',
'rgba(238, 197, 102, 1)'
].reverse()
}
},
splitArea: {
// 分割区域
show: false
},
axisLine: {
// 坐标轴轴线
lineStyle: {
color: 'rgba(238, 197, 102, 0.5)'
}
}
},
series: this.provinces.map((province, idx) => {
return {
name: province,
type: 'radar',
lineStyle: {
width: 1,
opacity: 0.5
},
data: this.currentData[idx].data,
symbol: 'none',
itemStyle: {
color: colors[idx % colors.length]
},
areaStyle: {
opacity: 0.05
}
};
})
};
}
},
methods: {
...mapActions('charts', ['changeData'])
},
// 组件装载前请求数据
async beforeMount() {
const path = '/radar';
const key = 'radar';
await this.changeData({ path, key });
},
components: { Chart }
};
</script>
<style lang="scss" scoped>
@import '../scss/_common.scss';
</style>