在Vue中封装Echarts并使用

耗尽温柔 提交于 2021-01-02 10:48:16

为什么要封装


  • 如果不封装,每用一次图表,都要重新配置一边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实例的父元素大小改变也会使其变形,所以我们还要对其父元素大小改变进行监听,做到完全的自适应。

写在最后

如有不足,欢迎指正。
对源码感兴趣欢迎访问我的github

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!