关于标题,想不出什么好的叙述方式,在使用图表ECharts这个JS库的时候,相信很多时候都需要对数据动态处理后,加载到图表中。这个时候,通用的方式就是基于ECharts的setOption(Object, true)方法了。最近在用vue-cli脚手架工具想构建一个多种图表的展示页,主要的功能上就是发送数据请求,接收数据,渲染图表。官网关于ECharts的案例都是基于原生语法,首要工作就是将原生的语法改装安置到Vue组件中!

ECharts 和 Vue-Echarts

ECharts:百度前端团队开发的一款图表可视化的JS库。

Vue-Echarts:ECharts 的 Vue.js 组件。基于ECharts v4.0.1+,依赖Vue.js v2.2.6 +。

安装方式上不多赘述:npm方式最为推荐,当然也可以下载源码在HTML中引入js文件。

npm install --save echarts vue-echarts-v3

Vue-Cli 2 的 webpack 模板需要在配置中进行变更

坐标:build/webpack.base.conf.js,注意是 webpack 2.x 版本

{
  test: /\.js$/,
  loader: 'babel-loader',
  include: [resolve('src'), resolve('test'), 
            resolve('node_modules/vue-echarts-v3/src')]
}

组件组织结构

├── APP.vue                   # 根组件
    └── Chart.vue             # 图表父组件
        ├── Line.vue          # 标准折线图子组件
        ├── Radar.vue         # 标准雷达图子组件
        ├── Gauge.vue         # 标准仪表盘子组件
        |    └── IEchart.vue   # vue-echarts 组件封装图表实例(孙组件)
        └── ....              # 图表子组件

基础的组件层级就是这样了,由于现在各大论坛、博客网站可找到关于vue-echarts的资料较少。
我为什么会选择vue-echarts组件,在组件相关资料如此稀有的情况下?

  1. 组件化思想的影响,上述组织层级中的IEChart组件部分,完全可以引入ECharts,选定DOM进行操作。
    比如这样:

     // 引入Echarts.js
     <script src="public/js/echarts.common.min.js"></script>
     // 准备具备高宽的DOM容器
     <div id="echart" style="width:600px;height:400px;"></div>
     // 初始化echarts实例,通过setOption方法生成需要的图表类型
     methods: {
       draw() {
         this.lineObj = echarts.init(document.getElementById('echart'));
         // 图表类型在原生的option属性中:series.type = 'line'
         this.lineObj.setOption(option); 
       }
     }
     // 组件加载时使用钩子函数调用上述画图方法
     mounted() {
       this.draw()
     }
    
  2. 组件化的调用方式Gauge.vue 标准仪表盘子组件

     // 模板
     <IEcharts :option="gauge"></IEcharts>
     
     // 引入方面,不建议引入full.js,按需引入需要的图表js
     import IEcharts from "vue-echarts-v3/src/lite.js";
     import "echarts/lib/chart/gauge";
     
     // 组件注册
     components: {Echarts}
    
     // 组件option配置,这里绑定到了gauge对象中,因此在data、computed中直接操作gauge即可
    

官网案例:标准仪表盘

案例地址:http://echarts.baidu.com/echarts2/doc/example/gauge1.html

简要介绍下案例的组成:

  1. 图表实例option配置
  2. setInterval方法动态加载配置数据,实现动态效果

关于option属性的相关配置不多赘述,可以参照相关资料进行配置。
这里推荐一个关于ECharts图表使用的技术专栏:https://blog.csdn.net/luanpeng825485697/column/info/17191

计算属性配置图表option

这里给出两种网络上的通用方案:

  1. 从父组件Chart中获取数据,子组件通过props属性进行接收,并在data中对图表实例IEchart的option属性进行配置。(如:series[0].data中的数据配置)

  2. 子组件从接口动态获取数据(axios获取),获取数据配置在data中,而图表实例IEChart中的option属性配置转移至computed 计算属性中返回回来

     computed: {
       // gauge 对应 模板组件中的 option
       gauge: function() {
         return {
           title: {
             // data 传入数据
             text: this.msg,
             subtext: "业务指标"
           },
           tooltip: {
             formatter: "{a} <br/>{b} : {c}%"
           },
           toolbox: {
             show: true,
             feature: {
               mark: { show: true },
               restore: { show: true },
               saveAsImage: { show: true }
             }
           },
           series: [
             {
               name: "业务指标",
               type: "gauge",
               detail: { formatter: "{value}%" },
               data: [{ value: 50, name: "完成率" }]
             }
           ]
         };
       }
     }
    

    上述代码就将gauge(option)属性配置移至计算属性中进行,在计算属性中可以直接使用data中的数据值。

     data() {
       return {
         msg: "标准仪表盘 Demo"
       };
     }
    

在这里插入图片描述

setInterval方法动态加载配置数据,实现动态效果

注意:官网案例所给出的该部分的代码基于ECharts,在vue-echarts中相关方法API做了整合,因此有些方法是无法直接使用的。

案例源码:

clearInterval(timeTicket);
timeTicket = setInterval(function (){
    option.series[0].data[0].value = (Math.random()*100).toFixed(2) - 0;
    myChart.setOption(option, true);
},2000);

分析:

  1. HTML DOM clearInterval() 方法

     clearInterval() 方法可取消由 setInterval() 设置的 timeout。
     clearInterval() 方法的参数必须是由 setInterval() 返回的 ID 值。
    
  2. HTML DOM setInterval() 方法

     setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
     setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
     由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。
    

上述两个Window对象的方法是配套使用的,由此可见该动态效果的实现逻辑便是 setInterval()内的function。


改造开始
  1. 首先将setInterval()内部的逻辑重构成方法:getRate()

     methods: {
       getRate: function() {
         // 获取计算属性 IEchart组件 option 对象
         const that = this.gauge;
         that.series[0].data[0] = (Math.random() * 100).toFixed(2) - 0;
         // 2018年12月12日18:57:19 当对IEChart组件数据进行变更后,需要同步配置重新绘图
         this.$refs.echarts_gauge.mergeOption(that);
       }
     }
    

    关于 that 对象内容如下图:
    在这里插入图片描述
    关于js中constvarlet 的区别,三句话总结:

    1. const定义的变量不可以修改,而且必须初始化。
    2. var定义的变量可以修改,如果不初始化会输出undefined,不会报错。
    3. let是块级作用域变量,函数内部使用let定义后,对函数外部无影响。
  2. this.$refs.echarts_gauge.mergeOption(that); 同步配置关键代码

    通过上述说明,我们已经将option.series[0].data中的数据做了变更,接下来需要重新绘制图表(将数据配置应用),案例中使用了原生ECharts的setOption方法进行了配置,而在IEChart组件中无此方法。我们需要使用IEchart封装的mergeOption()方法。但在此之前需要做的一件事就是获取对应案例中的 myChart 对象(DOM容器绑定)。

    在Vue组件模板中我们引入了IEChart这个组件,这个组件便对应了参考案例中的 myChart 对象。
    一般来讲,获取DOM元素,需要document.querySelector(".selector")获取这个dom节点,然后在获取selector的值。
    在Vue中,提供了 ref 属性来获取到DOM元素或者是子组件,这里需要注意在2.x 版本,ref 取代了 el。

    1. Gauge组件模板添加 ref (注意ref属性的命名不能用驼峰式,同时获取的时候也不能用)

     <IEcharts :option="gauge" ref="echarts_gauge"></IEcharts>
    

    2. this.$refs.echarts_gauge 获取组件对象
    在这里插入图片描述
    3.mergeOption()方法

    • 首先给出vue-echarts组件使用的中文文档地址:
      https://github.com/ecomfe/vue-echarts/blob/master/README.zh_CN.md

    • 其中Props章节叙述了关于setOption的配置要求:
      在这里插入图片描述
      我们的做法就是上图中标注的这种,关于notMerge,我们查看vue-echarts-v3/src目录下的wrapper.js文件。
      在这里插入图片描述
      可以看出,notMerge 的默认值为:false

      以下也给出了针对响应式的渲染场景下,关于数据监听的配置:
      在这里插入图片描述

    • mergeOption(opts)方法

    在这里插入图片描述
    我们到wrapper.js文件下一探究竟:

         mergeOption: function(opts) {
           const that = this;
           if (that.instance) {
             that.instance.setOption(opts, false, that.lazyUpdate);
             that.resize();
           }
         }
    

    这里是获取了底层ECharts实例,这里的setOption方法中可参考官方API:
    在这里插入图片描述
    关于setOption第二个参数:notMerge(不合并),封装默认为 false,即合并。所以封装后的方法名为:mergeOption()

    所以,这条关键代码也就解释清楚了!

    this.$refs.echarts_gauge.mergeOption(that);

  3. clearInterval and setInterval

    这里交给钩子函数来完成:mounted()

     mounted() {
       // 首次调用获取第一次需要加载的数据
       this.getRate();
       // 每隔2秒再次进行数据加载
       clearInterval(flag);
       let flag = setInterval(this.getRate, 2000);
     }
    
  4. 完成效果:
    在这里插入图片描述

  5. 不得不说,图表就是上档次,在图表Demo项目中,在该过程中遇到的,我会及时整理总结的。
    在这里插入图片描述

Logo

前往低代码交流专区

更多推荐