如何在vue中封装一个高适用性、高扩展性的echarts

武汉解封,又是一年春好色!

不管有事没事,我总喜欢把公司的项目拿出来da东看看,西点点,或许我是做测试的命吧。今天发现了一个问题,谈不上bug,但是体验不好。下面先上图,看看问题所在,(敏感数据已做处理)

全屏下是这个样子的,中规中矩,看起来还行:

如果我们把侧边栏打开,他就成了这个鬼样子:

不用多说,想必大家已经知道问题所在了吧,下面的table用的是el-row + el-col栅格布局,自然会适应屏幕大小尺寸的变化;而我们的echarts图表可没有什么栅格布局;仔细阅读echarts官方文档的同学,自然知道resize()这个方法,那么我们要做的其实就是echarts的尺寸变化时调用resize()方法。

下面先直接上代码,后续再解释:

<template>
  <div ref="chartDom"></div>
</template>
<script>
import echarts from 'echarts'
// vue中监听元素大小(尺寸)变化
import { addListener, removeListener } from 'resize-detector'
// 防抖
import debounce from 'lodash/debounce'
export default {
  props: {
    option: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
    }
  },
  watch: {
    option: {
      handler(val) {
        this.chart.setOption(this.option)
      },
      deep: true
    }
  },
  created() {
    this.resize = debounce(this.resize, 300)
  },
  mounted() {
    this.renderCharts()
    addListener(this.$refs.chartDom, this.resize)
  },
  beforeDestroy() {
    // 销毁echart实例,防止内存溢出
    removeListener(this.$refs.chartDom, this.resize)
    this.chart.dispose()
    this.chart = null
  },
  methods: {
    resize() {
      this.chart.resize()
    },
    // 图表渲染
    renderCharts() {
      this.chart = echarts.init(this.$refs.chartDom)
      this.chart.setOption(this.option)
    }
  }
}
</script>

好的,仔细讲解下面几个点:

  • 安装依赖:npm i echarts resize-detector lodash --save  ( resize-detector 监听元素尺寸变化; lodash工具函数)
  • 为了高扩展性,echarts中的数据/参数都是从父组件中传递过来的,我们封装的组件不需要关心数据
  • addListener监听dom元素尺寸的变化,一旦发生变化则调用echarts官方提供的resize()方法
  • 需要注意和防抖函数的结合,提高性能
  • 为了数据实时响应,视图立即更新,需要监听option的变化,不过深度监听比较耗性能,可以在父组件中对option进行赋值
  • 为了防止内存溢出等,在钩子函数中销毁echarts实例

大功告成,上面的代码,是拿来即食的那种,但是别忘了安装相关的依赖。

下面我们就来体验一把:

<template>
  <div>
    <h5 style="text-align:center;">echarts图表的封装</h5>
    <Charts v-if="chartOption" :option="chartOption" style="height:600px;"></Charts>
  </div>
</template>
<script>
import Charts from './components/Charts'
export default {
  components: {
    Charts
  },
  data() {
    return {
      chartOption: null
    }
  },
  created() {
    this.getChartsData()
    // this.changeData()
  },
  methods: {
    //这里就是上面所说的手动赋值
    // changeData() {
    //   setInterval(() => {
    //     this.chartOption.series[0].data = [100, 150, 50, 200, 120, 700]
    //   }, 5000)
    // },
    getChartsData() {
      setTimeout(() => {
        this.chartOption = {
          title: {
            text: '疯狂测试'
          },
          tooltip: {
            trigger: 'item'
          },
          xAxis: {
            data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
          },
          yAxis: {},
          series: [{
            name: '销量',
            type: 'pie',
            data: [100, 150, 50, 200, 120, 300]
          }]
        }
      }, 1000)
    }
  }
}
</script>

给我一瓶酒,再给我一支烟,说走就走,我有的是时间.....

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章