VUE中使用Echarts


最近公司开发做报表统计,需要用到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官方文档写得真是清晰明了,直接用着也很爽呀完全没问题。

Author: 顺坚
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source 顺坚 !
评论
 Previous
Echarts图表各种参数详解 Echarts图表各种参数详解
公司做项目需要报表统计,用到Echarts。但是UI给出的风格和Echarts官方的风格差别有点大,因此需要自己去调整报表的风格样式,官方文档非常详细。但是每次都要去不同的菜单下去查看文档也很麻烦,在使用过程中个人对报表的统计参数做了一些总
2020-03-12
Next 
IDEA永久破解 IDEA永久破解
IDEA是目前最流行也是最好用的集成开发工具,强大的代码提示和编辑功能吸引了很多开发者,Jetbrains下还有很多类似的开发工具,也很受开发者青睐。Jetbrains下的产品都是商业付费版,因此购买才可以使用,这对于普通开发者和学生党来说
2020-03-07
  TOC