zoukankan      html  css  js  c++  java
  • echarts 组件复用

    echarts 组件复用

    在前端开发过程中经常会遇到使用 echarts 报表的功能,有很多时候在一个页面或者是一个项目当中使用相同的 echarts 表,比如使用好几个柱状图、折线图之类的,而这些柱状图的样式是完全一样的,只是横纵坐标的数据不一样,因此我们可以将样式相同的 echarts 图表封装成一个组件,然后在需要使用的时候直接调用组件,传入x轴、y轴数据或者是其他的标题之类的数据就可以使用,不需要每个图表都单独创建一个组件去调用,从而减少代码量,提高组件复用性。

    创建一个 bar 组件封装 echarts 报表

    <template>
      <div style=" 100%;height: calc(100% - 25px);">
        <div id="top" style=" 100%;height:100%;"></div>
      </div>
    </template>
    <script>
      import echarts from 'echarts'
      // 引入改变窗口重新加载图表js。这个文件看之前的博客,有使用介绍
      import { EleResize } from '../../../../../../public/js/esresize.js'
      import 'echarts-gl'
    
      export default {
        name: '',
        props: ['showData'],
        data() {
          return {
            charts: '',
          }
        },
        watch: {
          showData() {
            this.$nextTick(function () {
              this.drawMap('top')
            })
          }
        },
        created() {
          this.$nextTick(function () {
            this.drawMap('top')
          })
        },
        methods: {
          drawMap(id) {
            let option = {
              color: ['#3398DB'],
              tooltip: {
                trigger: 'axis',
                axisPointer: {            // 坐标轴指示器,坐标轴触发有效
                  type: 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
                }
              },
              grid: {
                left: '3%',
                right: '3%',
                bottom: '0%',
                top: '10%',
                containLabel: true
              },
              xAxis: [
                {
                  type: 'category',
                  boundaryGap: true,
                  data: this.showData.xValue,
                  axisTick: {
                    show: false
                  },
                  axisLine: {
                    lineStyle: {
                      color: "#9e9fa3",
                       0,
                    },
                  },
                }
              ],
              yAxis: [
                {
                  type: 'value',
                  axisLabel: {
                    margin: 15,
                    formatter: "{value}",
                    textStyle: {
                      color: "#9e9fa3",
                    },
                  },
                  axisTick: {
                    show: false
                  },
                  splitLine: {
                    lineStyle: {
                      color: "#c8c9cb",
                      type: "dashed"
                    },
                  },
                  axisLine: {
                    show: false,
                    lineStyle: {
                      color: "#9e9fa3",
                    },
                  },
                }
              ],
              series: [
                {
                  name: '数据',
                  type: 'bar',
                  barWidth: '50%',
                  data: this.showData.yValue
                }
              ]
            };
    
            this.charts = echarts.init(document.getElementById(id))
            // 改变屏幕大小图表重新加载
            var resizeDiv = document.getElementById(id)
            var listener = () => {
              this.charts.resize()
            }
            EleResize.on(resizeDiv, listener)
            this.charts.clear()
            this.charts.setOption(option)
          }
        },
        // 调用
        mounted() { },
        // 销毁
        destroyed() {
          // 销毁echarts图表
          this.charts.dispose()
        }
      }
    </script>
    

    如果单独每个echarts图表写一个vue组件按照上面就可以了。

    showData是一个对象,里面有两个列表,xValue 是 x 轴数据,yValue 是 y 轴数据,然后放到相应的地方渲染就可以了。

    留坑

    但是这个组件是不可以复用的,如果有一个和这个图表样式相同的报表,再次调用传进 showData 数据会发现渲染不对,出问题,为什么,因为 echarts 渲染的时候,需要先创建一个 div 标签设置长宽渲染 echarts 图表,但是有一个问题,渲染的时候需要这个 div 有一个唯一的 id 值,这样的话,如果两个图表调用这同一个封装好的组件会有两个 id 相同的 div,因此会出现渲染问题。

    填坑

    这样的话,就需要在每次调用组件的时候,需要设置一个唯一 id 的 div 来渲染不同位置的 echarts 图表。

    修改之前的代码:

    <template>
      <div style=" 100%;height: calc(100% - 25px);">
      	<!-- 假设有三个位置 top center bottom 需要渲染这个组件,需要创建三个div来渲染图表
      	     判断通过传进的id值,来判断渲染哪一个div -->
        <div id="top" style=" 100%;height:100%;" v-if="id==='top'"></div>
        <div id="center" style=" 100%; height: 100%;" v-if="id==='center'"></div>
        <div id="bottom" style=" 100%; height: 100%;" v-if="id==='bottom'"></div>
      </div>
    </template>
    <script>
      import echarts from 'echarts'
      // 引入改变窗口重新加载图表js
      import { EleResize } from '../../../../../../public/js/esresize.js'
      import 'echarts-gl'
    
      export default {
        name: '',
        props: ['showData', 'id', 'unit'],  // showData是xy轴数据,id是div id值,unit是单位
        data() {
          return {
            charts: '',
          }
        },
        watch: {
          showData() {
            this.$nextTick(function () {
              switch (this.id) {
                case 'top':
                  this.drawMap('top')
                  break;
                case 'center':
                  this.drawMap('center')
                  break;
                case 'bottom':
                  this.drawMap('bottom')
                  break;
              }
            })
          }
        },
        created() {
          this.$nextTick(function () {
            switch (this.id) {
              case 'top':
                this.drawMap('top')
                break;
              case 'center':
                this.drawMap('center')
                break;
              case 'bottom':
                this.drawMap('bottom')
                break;
            }
          })
        },
        methods: {
          drawMap(id) {
            let option = {
              color: ['#3398DB'],
              tooltip: {
                trigger: 'axis',
                axisPointer: {            // 坐标轴指示器,坐标轴触发有效
                  type: 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
                }
              },
              grid: {
                left: '3%',
                right: '3%',
                bottom: '0%',
                top: '10%',
                containLabel: true
              },
              xAxis: [
                {
                  type: 'category',
                  boundaryGap: true,
                  data: this.showData.xValue,
                  axisTick: {
                    show: false
                  },
                  axisLine: {
                    lineStyle: {
                      color: "#9e9fa3",
                       0,
                    },
                  },
                }
              ],
              yAxis: [
                {
                  type: 'value',
                  axisLabel: {
                    margin: 15,
                    formatter: "{value}",
                    textStyle: {
                      color: "#9e9fa3",
                    },
                  },
                  axisTick: {
                    show: false
                  },
                  splitLine: {
                    lineStyle: {
                      color: "#c8c9cb",
                      type: "dashed"
                    },
                  },
                  axisLine: {
                    show: false,
                    lineStyle: {
                      color: "#9e9fa3",
                    },
                  },
                }
              ],
              series: [
                {
                  name: this.unit,
                  type: 'bar',
                  barWidth: '50%',
                  data: this.showData.yValue
                }
              ]
            };
    
            this.charts = echarts.init(document.getElementById(id))
            // 改变屏幕大小图表重新加载
            var resizeDiv = document.getElementById(id)
            var listener = () => {
              this.charts.resize()
            }
            EleResize.on(resizeDiv, listener)
            this.charts.clear()
            this.charts.setOption(option)
          }
        },
        // 调用
        mounted() { },
        // 销毁
        destroyed() {
          // 销毁echarts图表
          this.charts.dispose()
        }
      }
    </script>
    <style scoped>
      * {
        margin: 0;
        padding: 0;
        list-style: none;
      }
    </style> 
    

    这样的话就可以在三个地方渲染这样的这个组件,但是如果有新位置也需要在加 div,也比每个图表创建一个 Vue 文件要方便许多,而且需要修改样式就可以修改这一个文件就可以了,不需要一个一个修改。

    然后调用的时候:

    <echart-bar :id="'center'" :showData="barCenter" :unit="'占比'"></echart-bar>
    <echart-bar :id="'bottom'" :showData="bottomCenter" :unit="'数量'"></echart-bar>
    

    图就暂时不截了...

    优化

    其实还有一个简单的方法,一直没说,因为上面基本上说的就是原理之类的解决方法,如果理解上面的骚操作,优化的方法不说估计也能想到。

    提示: 传进来的 id 直接赋值给 div 的 id ,就不需要每次创建 div 设置唯一的 id 了 。

    还有别的办法,ref ....

    好了,可以点赞、关注、加评论了~ 哈哈哈哈!

  • 相关阅读:
    整型数字转utf8
    cmake构建时指定编译器架构(x86 or x64)
    tcp echo server libuv
    VS2015编译boost1.62
    android rom开发
    游戏昵称
    乐观锁和悲观锁
    数据库锁机制
    MySQL事务实现原理
    MySQL事务
  • 原文地址:https://www.cnblogs.com/wjw1014/p/13862719.html
Copyright © 2011-2022 走看看