最近公司开发做报表统计,需要用到echarts。官网上的echarts是操作dom节点来初始化画布的,那么在使用vue作为前端开发框架的时候,这种方式显然不够优雅。于是想着把echarts封装成一个公共组件,在需要使用的地方直接引用组件,通过组件参数传入相应的数据即可。故在此记录下来,不过在我把echarts封装成组件后,发现在NPM库中有一个别人封装好的组件可以直接使用叫vue-echarts
,但在封装过程中也有收获,体会到了vue组件化思想的强大能力。自己封装了可以个性化的东西更多,用开源vue组件可以直接上手,拿来主义;算各有优势吧。下面我将介绍这两种方式
一. 组件化Echarts
首先先在项目中导入echarts,这里通过npm命令导入即可。然后再把echarts挂载到vue的原型链上,以便组件中直接引用原生的echarts组件,命令如下
npm install echarts --save
然后在项目的main.js中挂载echarts到vue的原型链上
import Echarts from 'echarts'
Vue.use(Echarts);
封装echarts
在工程中创建一个base目录,用于存放项目中最基础的组件,将要封装echarts组件放在这个目录下,并命名为BaseEcharts.vue
,当然这个命名随个人喜好。组件代码如下
<template>
<div>
<div class="echarts" :id="randomId" style="height: 100%"></div>
</div>
</template>
<script type="text/ecmascript-6">
import echarts from 'echarts'
export default {
name: 'echarts',
props: {
option: {
type: Object,
default(){
return {}
}
},
randomId: {
type: String,
default() {
return 'myChart'
}
}
},
data() {
return {}
},
mounted() {
//# 1. 获取一个用于挂在 echarts 的 DOM 元素
let $echartsDOM = document.getElementById(this.randomId);
//# 2. 初始化
this.myEcharts = echarts.init($echartsDOM);
this.checkAndSetOption()
},
beforeDestroy() { //组件卸载释放chart内存
if(!!this.myEcharts) {
this.myEcharts.clear(); //清空图表
this.myEcharts.dispose(); //释放图表组件
this.myEcharts = null;
}
},
watch: {
option(option){
this.checkAndSetOption()
}
},
methods: {
checkAndSetOption(){
function isValidOption(option){
return isObject(option) && !isEmptyObject(option)
&& hasSeriesKey(option)
&& isSeriesArray(option) && !isSeriesEmpty(option)
}
function isObject(option) {
return Object.prototype.isPrototypeOf(option)
}
function isEmptyObject(option){
return Object.keys(option).length === 0
}
function hasSeriesKey(option){
return !!option['series']
}
function isSeriesArray(option) {
return Array.isArray(option['series'])
}
function isSeriesEmpty(option){
return option['series'].length === 0
}
let option = this.option; //配置等于父组件传过来的数据
if(isValidOption(option)){
this.myEcharts.setOption(option); //渲染出来
this.myEcharts.hideLoading(); //隐藏加载动画
}else{
this.myEcharts.showLoading(); //加载动画
}
}
}
}
</script>
使用
创建一个测试组件MyEcharts.vue
,在该组件中引入刚刚封装好的BaseEcharts组件,直接使用就可以了
<template>
<div class="block" style="padding: 15px">
<chart class="echarts-container" :randomId="chart1" :option="option1" style="height: 600px;width: 45%;display: inline-block;margin: 10px"></chart>
<chart class="echarts-container" :randomId="chart4" :option="option4" style="height: 600px;width: 45%;display: inline-block;margin: 10px"></chart>
</div>
</template>
<script type="text/ecmascript-6">
import chart from '../base/Echarts'
export default {
name: 'app',
components: {
chart
},
data() {
return {
chart1:'chart1',
chart4:'chart4',
option1: {},
option4: {}
}
},
created(){
//柱状图
this.option1={
title : {
text: '某地区蒸发量和降水量',
subtext: '纯属虚构'
},
tooltip : {
trigger: 'axis'
},
legend: {
data:['蒸发量','降水量']
},
toolbox: {
show : true,
feature : {
dataView : {show: true, readOnly: false},
magicType : {show: true, type: ['line', 'bar']},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable : true,
xAxis : [
{
type : 'category',
data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']
}
],
yAxis : [
{
type : 'value'
}
],
series : [
{
name:'蒸发量',
type:'bar',
data:[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3],
markPoint : {
data : [
{type : 'max', name: '最大值'},
{type : 'min', name: '最小值'}
]
},
markLine : {
data : [
{type : 'average', name: '平均值'}
]
}
},
{
name:'降水量',
type:'bar',
data:[2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3],
markPoint : {
data : [
{name : '年最高', value : 182.2, xAxis: 7, yAxis: 183},
{name : '年最低', value : 2.3, xAxis: 11, yAxis: 3}
]
},
markLine : {
data : [
{type : 'average', name : '平均值'}
]
}
}
]
};
this.option4 = {
backgroundColor: '#2c343c',
title: {
text: 'Customized Pie',
left: 'center',
top: 20,
textStyle: {
color: '#ccc'
}
},
tooltip : {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
visualMap: {
show: false,
min: 80,
max: 600,
inRange: {
colorLightness: [0, 1]
}
},
series : [
{
name:'访问来源',
type:'pie',
radius : '55%',
center: ['50%', '50%'],
data:[
{value:335, name:'直接访问'},
{value:310, name:'邮件营销'},
{value:274, name:'联盟广告'},
{value:235, name:'视频广告'},
{value:400, name:'搜索引擎'}
].sort(function (a, b) { return a.value - b.value; }),
roseType: 'radius',
label: {
normal: {
textStyle: {
color: 'rgba(255, 255, 255, 0.3)'
}
}
},
labelLine: {
normal: {
lineStyle: {
color: 'rgba(255, 255, 255, 0.3)'
},
smooth: 0.2,
length: 10,
length2: 20
}
},
itemStyle: {
normal: {
color: '#c23531',
shadowBlur: 200,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
animationType: 'scale',
animationEasing: 'elasticOut',
animationDelay: function (idx) {
return Math.random() * 200;
}
}
]
};
}
}
</script>
二. 使用vue-echarts
同样的通过npm导入,在main.js中挂载到原型链上,命令如下
npm install echarts vue-echarts
在main.js中,除了全量引用echarts,我们还可以采用按需引入的方式,但是全局引入会将所有的echarts图表打包,导致体积过大,所以如果仅仅只是少量的报表还是按需引入吧。
import ECharts from 'vue-echarts'
import 'echarts/lib/chart/line'
Vue.component('chart', ECharts)
创建一个HelloWorld.vue
测试一下,代码如下
<template>
<div class="hello">
<chart ref="chart1" :options="orgOptions" :auto-resize="true"></chart>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
orgOptions: {},
}
},
mounted() {
this.orgOptions = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
smooth: true
}]
}
}
}
</script>
到这里就结束了。是不是很简单,毕竟是别人造好的轮子,只管用就行了。
选择
两种方式都能满足常规的开发需求。个人认为:
- 如果你的需求是定制化比较少的,或者项目开发时间比较紧张,基本上绑定数据然后展示就行了,又或者你对echarts还不是很熟悉的,那么vue-echarts是一个不错的选择;
- 如果你的需求是定制化多的,比如需要特殊处理鼠标事件什么的(当然vue-echarts也可以,但需要同时看两份API文档,多累呀),又或者你已经对echarts比较熟悉了(那你就不会看这篇文章了哈哈),你会发现Echarts官方文档写得真是清晰明了,直接用着也很爽呀完全没问题。