在Vue中封装Echarts并使用

为什么要封装


  • 如果不封装,每用一次图表,都要重新配置一边option,封装起来方便复用,也方便统一管理。
  • 解决元素以及窗口的resize等问题。
  • 效果图以及项目目录


    1、效果图

    在这里插入图片描述

    2、项目目录

    在这里插入图片描述



  • 具体封装过程
  • 1、Echarts的安装

  • npm i echarts --save


  • 2、引入
  • 全部引入
  • 在你使用Echarts的.vue单文件直接使用以下语句引入:
  • import echarts from 'echarts'


  • 按需引入
  • 图省事可以整个引入,但是Echarts还是不小的,我们大部分只用到了其中的一部分功能,所以我推荐按需引入:

  • // 按需引入 引入 ECharts 主模块
  • var echarts = require('echarts/lib/echarts')
  • // 引入柱状图
  • require('echarts/lib/chart/pie')
  • // 引入提示框和标题组件
  • require('echarts/lib/component/tooltip')
  • require('echarts/lib/component/title')
  • require('echarts/lib/component/legend')

    如果你想用某个组件,但是不清楚该组件属于Echarts的哪一个组成部分,这时你可以查阅文档点进去鼠标往下翻两下就可以简单下面这张图了,里面说的也比较清楚:
    在这里插入图片描述

    3、封装案例
    此处以堆叠柱状图为例:BarChart.vue

    <template>

      <div :class="className" :style="{height:height,width:width}" />

    </template>

     

    <script>

    // 按需引入 引入 ECharts 主模块

    var echarts = require('echarts/lib/echarts')

    // 引入柱状图

    require('echarts/lib/chart/bar')

    // 引入提示框和标题组件

    require('echarts/lib/component/tooltip')

    require('echarts/lib/component/title')

    import chartResize from './mixins/chart-resize'

     

    export default {

      mixins:[chartResize],

      props: {

        className: {

          type: String,

          default: 'chart'

        },

        width: {

          type: String,

          default: '100%'

        },

        height: {

          type: String,

          default: '350px'

        },

        // 父组件传递过来的图表数据

        chartData: {

          type: Object,

          required: true

        }

      },

      data() {

        return {

          // Echarts实例

          chart: null

        }

      },

      watch: {

        /* 如果图表数据是后台获取的,监听父组件中的数据变化,重新触发Echarts */

        chartData: {

          deep: true,

          handler(val) {

            this.setOptions(val)

          }

        }

      },

      mounted() {

        /* 图表初始化 */

        this.$nextTick(() => {

          this.initChart()

        })

      },

      beforeDestroy() {

        if (!this.chart) {

          return

        }

        /* 释放图表实例 */

        this.chart.dispose()

        /* dispose 会释放内部占用的一些资源和事件绑定,但是解除实例的引用我们是做不到的,所以需要重新赋值为null */

        this.chart = null

      },

      methods: {

        initChart() {

          this.chart = echarts.init(this.$el)

          this.setOptions(this.chartData)

        },

        setOptions({ days, data1, data2 } = {}) {

          this.chart.setOption({

            title: {

              text: '堆叠柱状图',

              textStyle: {

                fontSize: 15

              }

            },

            tooltip: {

              trigger: 'axis',

              axisPointer: { // 坐标轴指示器,坐标轴触发有效

                type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'

              }

            },

            grid: {

              top: 35,

              left: '2%',

              right: '2%',

              bottom: '3%',

              containLabel: true

            },

            xAxis: [{

              type: 'category',

              data: days,

              axisTick: {

                alignWithLabel: true

              }

            }],

            yAxis: [{

              type: 'value',

              axisTick: {

                show: false

              }

            }],

            series: [{

              name: '数量一',

              type: 'bar',

              stack: 'vistors',

              barWidth: '60%',

              data: data1,

              animationDuration:2000

            },

            {

              name: '数量二',

              type: 'bar',

              stack: 'vistors',

              barWidth: '60%',

              data: data2,

              animationDuration:2000

            }]

          })

        }

      }

    }

    </script>

     

    • 在实际的情况当中,我们使用的图表数据一般都是从后台动态获取的,我们就需要对父组件传递过来的chartData进行监听,数据变化时,触发Echarts,进行视图的更新:
    • watch: {
    • /* 如果图表数据是后台获取的,监听父组件中的数据变化,重新触发Echarts */
    • chartData: {
    •   deep: true,
    •   handler(val) {
    •     this.setOptions(val)
    •   }
    • }
    • }

    • 在组件销毁时,请不要忘记以下操作,释放一定的内存空间:
    • beforeDestroy() {
    •     if (!this.chart) {
    •       return
    •     }
    •     /* 释放图表实例 */
    •     this.chart.dispose()
    •     /* dispose 会释放内部占用的一些资源和事件绑定,但是解除实例的引用我们是做不到的,所以需要重新赋值为null */
    •     this.chart = null
    •   },

    4、使用组件的页面

    • index.vue

      <template>

        <div id="echarts-container">

          <el-row :gutter="20">

            <el-col :span="12">

              <div class="grid-content bg-purple">

                <bar-chart :chartData="barChartData"/>

              </div>

            </el-col>

            <el-col :span="12">

              <div class="grid-content bg-purple">

                <rose-chart />

              </div>

            </el-col>

          </el-row>

          <el-row style="background-color:#fff">

            <line-chart :chartData="lineChartData" />

          </el-row>

        </div>

      </template>

      <script>

      // 引入组件

      import BarChart from './components/BarChart'

      import RoseChart from './components/RoseChart'

      import LineChart from './components/LineChart'

      export default {

        // 注册局部组件

        components:{

          BarChart,

          RoseChart,

          LineChart

        },

        data() {

          return {

            // 柱状图数据

            barChartData: {

              days: ['11.21', '11.22', '11.23', '11.24', '11.25', '11.26', '11.27'],

              data1: [100, 120, 161, 134, 105, 160, 165],

              data2: [120, 82, 91, 154, 162, 140, 145]

            },

            // 折线图数据

            lineChartData: {

              expectedData: [4, 9, 12, 11, 5, 2, 9],

              actualData: [10, 4, 3, 11, 13, 10, 7]

            }

          }

        }

      }

      </script>

      <style lang="less" scoped>

      #echarts-container{

        width: 100%;

        height: 100%;

        background-color: #F0F2F5;

        .el-row {

          margin-bottom: 20px;

          &:last-child {

            margin-bottom: 0;

          }

        }

        .el-col {

          border-radius: 4px;

        }

        .bg-purple-dark {

          background: #99a9bf;

        }

        .bg-purple {

          background: #fff;

        }

        .bg-purple-light {

          background: #e5e9f2;

        }

        .grid-content {

          border-radius: 4px;

          min-height: 36px;

        }

        .row-bg {

          padding: 10px 0;

          background-color: #f9fafc;

        }

      }

      </style>

    • 在这个页面简单的使用了Element-UI的栅格布局。
      在使用自己封装的Echarts组件时,也进行了数据的传入。

      5、使用mixins解决resize问题
      Echarts有更新数据的特性,以及窗口缩放时不能自适应的问题。这样导致数据更新了Echarts视图却没有更新,窗口缩放引起echarts图形变形问题。如下:
      窗口变化,但是视图却没有自适应,就导致出现显示的问题。

       

       

      但是使用了自定义的mixins之后,可以随着窗口的变化而自适应:
       
    •  

       自定义的mixins代码如下:chart-resize.js

      import ResizeListener from 'element-resize-detector';

      export default {

        methods: {

          /* 对chart元素尺寸进行监听,当发生变化时同步更新echart视图 */

          chartEleResizeListener() {

            const chartInstance = ResizeListener({

              strategy: 'scroll',

              callOnAdd: true

            });

            chartInstance.listenTo(this.$el, () => {

              if (!this.chart) return;

              this.chart.resize();

            });

          },

       

          /* 当窗口缩放时,echart动态调整自身大小 */

          windowResizeListener() {

            if (!this.chart) return;

            this.chart.resize();

          }

        },

        mounted() {

          window.addEventListener('resize', this.windowResizeListener);

          this.chartEleResizeListener();

        },

        beforeDestroy() {

          window.removeEventListener('resize', this.windowResizeListener);

        }

       

      }

    • 6、element-resize-detector

      是一个监听元素大小改变的插件,除了窗口的大小改变会引起变形之外,echart实例的父元素大小改变也会使其变形,所以我们还要对其父元素大小改变进行监听,做到完全的自适应。

具体封装过程1、Echarts的安装npm i echarts --save12、引入全部引入在你使用Echarts的.vue单文件直接使用以下语句引入:import echarts from 'echarts'1按需引入图省事可以整个引入,但是Echarts还是不小的,我们大部分只用到了其中的一部分功能,所以我推荐按需引入:// 按需引入 引入 ECharts 主模块var echarts = require('echarts/lib/echarts')// 引入柱状图require('echarts/lib/chart/pie')// 引入提示框和标题组件require('echarts/lib/component/tooltip')require('echarts/lib/component/title')require('echarts/lib/component/legend')12345678如果你想用某个组件,但是不清楚该组件属于Echarts的哪一个组成部分,这时你可以查阅文档,点进去鼠标往下翻两下就可以简单下面这张图了,里面说的也比较清楚:

3、封装案例此处以堆叠柱状图为例:BarChart.vue
<template>  <div :class="className" :style="{height:height,width:width}" /></template>
<script>// 按需引入 引入 ECharts 主模块var echarts = require('echarts/lib/echarts')// 引入柱状图require('echarts/lib/chart/bar')// 引入提示框和标题组件require('echarts/lib/component/tooltip')require('echarts/lib/component/title')import chartResize from './mixins/chart-resize'
export default {  mixins:[chartResize],  props: {    className: {      type: String,      default: 'chart'    },    width: {      type: String,      default: '100%'    },    height: {      type: String,      default: '350px'    },    // 父组件传递过来的图表数据    chartData: {      type: Object,      required: true    }  },  data() {    return {      // Echarts实例      chart: null    }  },  watch: {    /* 如果图表数据是后台获取的,监听父组件中的数据变化,重新触发Echarts */    chartData: {      deep: true,      handler(val) {        this.setOptions(val)      }    }  },  mounted() {    /* 图表初始化 */    this.$nextTick(() => {      this.initChart()    })  },  beforeDestroy() {    if (!this.chart) {      return    }    /* 释放图表实例 */    this.chart.dispose()    /* dispose 会释放内部占用的一些资源和事件绑定,但是解除实例的引用我们是做不到的,所以需要重新赋值为null */    this.chart = null  },  methods: {    initChart() {      this.chart = echarts.init(this.$el)      this.setOptions(this.chartData)    },    setOptions({ days, data1, data2 } = {}) {      this.chart.setOption({        title: {          text: '堆叠柱状图',          textStyle: {            fontSize: 15          }        },        tooltip: {          trigger: 'axis',          axisPointer: { // 坐标轴指示器,坐标轴触发有效            type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'          }        },        grid: {          top: 35,          left: '2%',          right: '2%',          bottom: '3%',          containLabel: true        },        xAxis: [{          type: 'category',          data: days,          axisTick: {            alignWithLabel: true          }        }],        yAxis: [{          type: 'value',          axisTick: {            show: false          }        }],        series: [{          name: '数量一',          type: 'bar',          stack: 'vistors',          barWidth: '60%',          data: data1,          animationDuration:2000        },        {          name: '数量二',          type: 'bar',          stack: 'vistors',          barWidth: '60%',          data: data2,          animationDuration:2000        }]      })    }  }}</script>
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126在实际的情况当中,我们使用的图表数据一般都是从后台动态获取的,我们就需要对父组件传递过来的chartData进行监听,数据变化时,触发Echarts,进行视图的更新:watch: {/* 如果图表数据是后台获取的,监听父组件中的数据变化,重新触发Echarts */chartData: {  deep: true,  handler(val) {    this.setOptions(val)  }}}123456789在组件销毁时,请不要忘记以下操作,释放一定的内存空间:beforeDestroy() {    if (!this.chart) {      return    }    /* 释放图表实例 */    this.chart.dispose()    /* dispose 会释放内部占用的一些资源和事件绑定,但是解除实例的引用我们是做不到的,所以需要重新赋值为null */    this.chart = null  },1234567894、使用组件的页面index.vue
<template>  <div id="echarts-container">    <el-row :gutter="20">      <el-col :span="12">        <div class="grid-content bg-purple">          <bar-chart :chartData="barChartData"/>        </div>      </el-col>      <el-col :span="12">        <div class="grid-content bg-purple">          <rose-chart />        </div>      </el-col>    </el-row>    <el-row style="background-color:#fff">      <line-chart :chartData="lineChartData" />    </el-row>  </div></template><script>// 引入组件import BarChart from './components/BarChart'import RoseChart from './components/RoseChart'import LineChart from './components/LineChart'export default {  // 注册局部组件  components:{    BarChart,    RoseChart,    LineChart  },  data() {    return {      // 柱状图数据      barChartData: {        days: ['11.21', '11.22', '11.23', '11.24', '11.25', '11.26', '11.27'],        data1: [100, 120, 161, 134, 105, 160, 165],        data2: [120, 82, 91, 154, 162, 140, 145]      },      // 折线图数据      lineChartData: {        expectedData: [4, 9, 12, 11, 5, 2, 9],        actualData: [10, 4, 3, 11, 13, 10, 7]      }    }  }}</script><style lang="less" scoped>#echarts-container{  width: 100%;  height: 100%;  background-color: #F0F2F5;  .el-row {    margin-bottom: 20px;    &:last-child {      margin-bottom: 0;    }  }  .el-col {    border-radius: 4px;  }  .bg-purple-dark {    background: #99a9bf;  }  .bg-purple {    background: #fff;  }  .bg-purple-light {    background: #e5e9f2;  }  .grid-content {    border-radius: 4px;    min-height: 36px;  }  .row-bg {    padding: 10px 0;    background-color: #f9fafc;  }}</style>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081在这个页面简单的使用了Element-UI的栅格布局。在使用自己封装的Echarts组件时,也进行了数据的传入。5、使用mixins解决resize问题Echarts有更新数据的特性,以及窗口缩放时不能自适应的问题。这样导致数据更新了Echarts视图却没有更新,窗口缩放引起echarts图形变形问题。如下:窗口变化,但是视图却没有自适应,就导致出现显示的问题。
但是使用了自定义的mixins之后,可以随着窗口的变化而自适应:
自定义的mixins代码如下:chart-resize.js
import ResizeListener from 'element-resize-detector';export default {  methods: {    /* 对chart元素尺寸进行监听,当发生变化时同步更新echart视图 */    chartEleResizeListener() {      const chartInstance = ResizeListener({        strategy: 'scroll',        callOnAdd: true      });      chartInstance.listenTo(this.$el, () => {        if (!this.chart) return;        this.chart.resize();      });    },
    /* 当窗口缩放时,echart动态调整自身大小 */    windowResizeListener() {      if (!this.chart) return;      this.chart.resize();    }  },  mounted() {    window.addEventListener('resize', this.windowResizeListener);    this.chartEleResizeListener();  },  beforeDestroy() {    window.removeEventListener('resize', this.windowResizeListener);  }}12345678910111213141516171819202122232425262728296、element-resize-detector是一个监听元素大小改变的插件,除了窗口的大小改变会引起变形之外,echart实例的父元素大小改变也会使其变形,所以我们还要对其父元素大小改变进行监听,做到完全的自适应。————————————————版权声明:本文为CSDN博主「一羊迁徙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/weixin_43242112/article/details/112016207
posted @ 2022-07-18 16:36  维丽的岁月  阅读(4568)  评论(0)    收藏  举报