vueCli 封装Echarts图表组件

写在前面


最近好长时间一直在做可视化项目,我采用的是echarts可视化图表工具画图,一开始由于时间的仓促,还有没有去研究,各方面原因吧,以前每次做图表之类的都没有封装,每次做图表都要从新去配置之类的,写了好多重复代码,感觉很累啊,所以自己把图表封装成子组件使用,代码工作量减轻了很多,而且子组件使用了数据进行监听和图表自适应屏幕大小,这样以后会方便很多了!简直帅到爆,不多说了,上思路和代码。

我用的是vue-cli全家桶+echarts,做的封装,先将代码贴出来,以便于学习以及帮助到小伙伴

首先用的脚手架需要先安装echarts,然后全局引入

npm install echarts --save
全局引入,main.js里边配置
// 引入echarts
import echarts from 'echarts'
Vue.prototype.$echarts = echarts
这样在每个页面就可以使用了

之前一开始都是每个页面配置,现在将其封装好,方便开发以及维护。下边为思路以及代码

StepOne: 在项目的components下新建一个文件夹Echarts,在其下边新建一个index.vue,里边存放公共的echarts组件。里边的注释我已经写的很全面了,还有不理解的评论。原理就是正常的父子组件传值。

由于Echarts/index.vue子组件在初始化就会加载,后期不会更新,再加上由于echarts采用的数据驱动,所以需要监听数据的变化来重绘图表

<template>
每一个图表都有自己唯一的id,所有需要动态传入。
  <div class="echartsLine"
       :id="id"
       :style="style"></div>
</template>
<script>
export default {
  props: {
    id: {
      type: String
    },
    width: {
      type: String,
      default: "100%"
    },
    height: {
      type: String
    },
    option: {
      type: Object
    }
  },
  data() {
    return {
      MyEcharts: "" //echarts实例
    };
  },
  computed: {
    style() {
      return {
        height: this.height,
        width: this.width
      };
    }
  },
  watch: {
    //要监听的对象 option
    //由于echarts采用的数据驱动,所以需要监听数据的变化来重绘图表
    option: {
      handler(newVal, oldVal) {
        if (this.MyEcharts) {
          if (newVal) {
            console.log(newVal);
           第一种方法:
           this.MyEcharts.setOption(newVal, true);
           第二种方法:
            let publicCharts = this.MyEchartsOption(newVal);
            console.log(publicCharts);
            this.MyEcharts.setOption(publicCharts, true);
          } else {
           第一种方法:
           this.MyEcharts.setOption(oldVal, true);
          第二种方法:
            let publicCharts = this.MyEchartsOption(oldVal);
            this.MyEcharts.setOption(publicCharts, true);
          }
        } else {
          this.InitCharts();
        }
      },
      deep: true //对象内部属性的监听,关键。
    }
  },
  mounted() {
    this.InitCharts();
  },
  methods: {
    //所设计的图表公共组件,不论第一种方法还是第二种方法都按照官网的格式来写数据,这样方便维护
    InitCharts() {
      this.MyEcharts = this.$echarts.init(document.getElementById(this.id));
      /**
       * Author  HaoYanFeng
       * 第一种
       * 此方法适用于所有项目的图表,但是每个配置都需要在父组件传进来,相当于每个图表的配置都需要写一遍,不是特别的省代码,主要是灵活度高
       * echarts的配置项,你可以直接在外边配置好,直接扔进来一个this.option
       */
       this.MyEcharts.clear(); //适用于大数据量的切换时图表绘制错误,先清空在重绘
      this.MyEcharts.setOption(this.option, true); //设置为true可以是图表切换数据时重新渲染
      /**
       * Author  HaoYanFeng
       * 第二种
       * 此方法不适用于所有项目,只适用于本项目,但是可以省好多代码,维护性高
       * 在这你还可以根据需求将你的配置项中公共的提取出来,这样就可以省很多代码
       */
      console.log(this.option);
      if (this.option.tooltip != undefined) {
        let publicCharts = this.MyEchartsOption(this.option);
        console.log(publicCharts);
        this.MyEcharts.clear(); //适用于大数据量的切换时图表绘制错误,先清空在重绘
        this.MyEcharts.setOption(publicCharts, true); //设置为true可以是图表切换数据时重新渲染
      }
   以下这种方法,当一个页面有多个图表时,会有一个bug那就是只有一个图表会随着窗口大小变化而变化,经过小编的努力,终于找到解决办法。
      window.onresize = () => {
        this.MyEcharts.resize();
      }; //当窗口变化时随浏览器大小而改变
以下为上边的bug的解决方案。以后用这种方案,放弃上一种。
      let _this = this;
      window.addEventListener("resize", function() {
        _this.MyEcharts.resize();
      });
    },
    /**
     * Author  HaoYanFeng
     * 第二种  公共的配置,省代码
     * 此方法不适用于所有项目,只适用于本项目,但是可以省好多代码,维护性高
     * 在这你还可以根据需求将你的配置项中公共的提取出来,这样就可以省很多代码
     */
    MyEchartsOption(configures) {
      if (configures.tooltip != undefined) {
        let MyOption = {
       //图标的标题   本项目暂未使用
          title: {
            // text: configures.title.text
          },
          //鼠标悬浮提示框
          tooltip: {
            trigger: "axis",
            confine: true, //是否将 tooltip 框限制在图表的区域内。  true为是
            axisPointer: {
              // 坐标轴指示器,坐标轴触发有效
              type: configures.tooltip.axisPointer.type // 默认为直线,可选为:'line' | 'shadow'
            },
            formatter: configures.tooltip.formatter
          },
          //图例
          legend: {
            //图例的数据数组
            // data: configures.legend.data, //图例的数据数组   一般不设置,自动根据数据匹配
            top: configures.legend.top, //图例组件离容器上侧的距离
            right: configures.legend.right, //图例组件离容器右侧的距离
            bottom: configures.legend.bottom, //图例组件离容器下侧的距离
            left: configures.legend.left, //图例组件离容器左侧的距离
            textStyle: {
              color: this.echartsXYcolor //在本项目中涉及到主题色切换,所以采用动态颜色,黑白两色,下边相同
            }
          },
          //工具栏。内置有导出图片,数据视图,动态类型切换,数据区域缩放,重置五个工具。
          // toolbox: {
          //   feature: {
          //     saveAsImage: {}
          //   }
          // },
          //直角坐标系内绘图网格
          grid: {
            top: configures.grid.top, //grid 组件离容器上侧的距离。也就是图表距离容器
            //在本项目中每个图表都是距左右下100px,这样的话就有一个缺点不灵活,但是适用于本项目,不需要每一个都修改,若要做灵活了就是如top写法,每个图表都要配置
            left: "100px",
            right: "100px",
            bottom: "100px"
          },
          //x轴的数据以及配置
          xAxis: {
            type: configures.xAxis.type, //坐标轴类型。具体参考官方文档
            boundaryGap: configures.xAxis.boundaryGap, //类目轴中 boundaryGap 可以配置为 true 和 false。默认为 true,这时候刻度只是作为分隔线,标签和数据点都会在两个刻度之间的带(band)中间。
            data: configures.xAxis.data, //x轴的数据
            axisLine: {
              lineStyle: {
                color: this.echartsXYcolor
              }
            },
            axisLabel: {
              textStyle: {
                color: this.echartsXYcolor
              }
            }
          },
          //y轴的数据配置
          yAxis: {
            axisLine: {
              lineStyle: {
                color: this.echartsXYcolor
              }
            },
            axisLabel: {
              textStyle: {
                color: this.echartsXYcolor
              },
              formatter: configures.yAxis.axisLabel.formatter
            }
          },
          // dataZoom 组件 用于区域缩放,从而能自由关注细节的数据信息,或者概览数据整体,或者去除离群点的影响。
          dataZoom: [
            {
              type: "inside"
            },
            {
              type: "slider",
              top: configures.dataZoom[1].top, //距离容器上边的距离
              textStyle: {
                color: this.echartsXYcolor
              }
            }
          ],
          //图表的数据
          series: configures.series //由于数据的灵活度大,所以完全采用传入的方式
        };
        return MyOption;
      }
    }
  }
};
</script>
<style lang="scss" scoped>
</style>

StepTwo:在使用页面例如有一个mycharts.vue文件,引用直接引入并传值就好了。

<template>
    <!-- 业绩表现 -->
    <div class="index">
            <MyEcharts :id="'exampleId'"
                       :style="{width: '100%', height: '380px'}"
                       :option="chartOption">
            </MyEcharts>
    </div>
</template>
import MyEcharts from "@/components/Echarts/index"; //echarts
export default {
  components: {
    MyEcharts
  },
  data() {
    return {
       chartOption: {},
     echartsXYcolor:"#fff000",
     lineColor:"#5bb1f0"
      }
},
mounted(){
   this.initCharts();
},
methods:{
   initCharts(){
        this.chartOption = {
         title: {
            text: '折线图'
          },
          tooltip: {
            trigger: "axis",
            confine: true, //是否将 tooltip 框限制在图表的区域内。  true为是
            axisPointer: {
              // 坐标轴指示器,坐标轴触发有效
              type: "line" // 默认为直线,可选为:'line' | 'shadow'
            },
            formatter: function(params) {
              return params;
            }
          },
          legend: {
            data:[],
            top: "93%",
            right:'center',
            bottom:"center",
            left:"center",
            textStyle: {
              color: this.echartsXYcolor
            }
          },
          // toolbox: {
          //   feature: {
          //     saveAsImage: {}
          //   }
          // },
          grid: {
            top: "3%",
            left: "100px",
            right: "100px",
            bottom: "100px"
          },
          xAxis: {
            type: "category",
            boundaryGap: false,
            data: data: ['周一','周二','周三','周四','周五','周六','周日'],
            axisLine: {
              lineStyle: {
                color: this.echartsXYcolor
              }
            },
            axisLabel: {
              textStyle: {
                color: this.echartsXYcolor
              }
            }
          },
          dataZoom: [
            {
              type: "inside"
            },
            {
              type: "slider",
              top: "82%",
              textStyle: {
                color: this.echartsXYcolor
              }
            }
          ],
          yAxis: {
            axisLine: {
              lineStyle: {
                color: this.echartsXYcolor
              }
            },
            axisLabel: {
              textStyle: {
                color: this.echartsXYcolor
              },
              formatter: function(val) {
                return (val * 1).toFixed(2) + "%";
              }
            }
          },
          series: [
            {
              name: '邮件营销',
              type: "line",
              lineStyle: {
                color: this.lineColor // 线的颜色
              },
              itemStyle: {
                color: this.lineColor// 图例的颜色
              },
              showSymbol: false, // 不显示symbol
             data:[120, 132, 101, 134, 90, 230, 210]
            }
          ]
        };
}
}
}

结束语


至此,一个完整的封装好的公共的vue-echarts组件就完工了,可以在项目中直接调用,里边都有公共的配置项,以及父组件完全传入配置两种方案,各有利弊,还有重绘,以及随浏览器大小而改变大小。希望简友可以提宝贵的意见在评论区评论。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • 基于Vue的一些资料 内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 element★...
    尝了又尝阅读 1,142评论 0 1
  • 这几天公司里边有一个项目,叫做日控制台,该项目是在webview下的一个webapp,使用vue构建,项目中要求使...
    剑来___阅读 8,032评论 2 9
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    小姜先森o0O阅读 9,422评论 0 72
  • Vue2.0+组件库总结 UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基...
    szch阅读 1,969评论 1 52
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    王喂马_阅读 6,452评论 1 77