当前位置:   article > 正文

echarts根据上级元素的大小自动更新echarts(element-resize-detector)配合防抖解决大屏页面卡顿的问题_elementresizedetectormaker

elementresizedetectormaker

echarts根据上级元素的大小自动更新echarts(element-resize-detector)

问题产生的原因:

在项目中有时需要因为其他样式的改变而被动改变echarts图例的大小,比如在我们管理系统中左侧的菜单栏的收缩,会导致右侧内容区的宽度变大,所以我们对应的echarts也要发生位置的变化:
我这里将所有echarts元素都始于一个chart组件,组价的价值主要在于生成一个dom,接受父级传入的echarts的options,并创建echarts图例:
代码:

<!--
 * @Descripttion: 
 * @version: 
 * @Author: ZhangJunQing
 * @Date: 2022-06-08 16:01:36
 * @LastEditors: ZhangJunQing
 * @LastEditTime: 2022-08-10 17:38:41
-->
<template>
  <div class="chart" ref="chartDom"></div>
</template>

<script>
export default {
  props: {
    option: {
      type: Object,
      required: true,
      default: {},
    },
  },
  data() {
    return {
      echartsInstance: null,
    };
  },
  methods: {
    init() {
      if (!this.echartsInstance) {
        let charts = this.$refs.chartDom;
        this.echartsInstance = this.$echarts.init(charts);
      }
      // this.echartsInstance.showLoading({
      //       text: '暂无数据',
      //       showSpinner: false,
      //       textColor: '#646464',
      //       maskColor: 'rgba(255, 255, 255, 1)',
      //       fontSize: '16px',
      //       fontWeight: 'bold',
      //     })
      this.echartsInstance.setOption(this.option);
      // this.echartsInstance.hideLoading()
    },
  },
  watch: {
    option: {
      handler(newOption) {
        this.echartsInstance.clear();
        this.echartsInstance.resize();
        this.echartsInstance.setOption(newOption);
      },
      deep: true
    },
  },
  mounted() {
    this.init();
  },
};
</script>

<style lang="less" scoped>
.chart {
  // width: 300px;
  // height: 300px;
  width: 100%;
  height: 100%;
}
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

但是有个问题,即便我们设置window自带的resize方法,但是我们改变左侧菜单的收缩,并不会出发resize方法,因为并没有改变当前页面的视图大小,于是使用了一个第三方插件,简直简直简直好用。

element-resize-detector

npm i element-resize-detector
  • 1

引入:

import elementResizeDetectorMaker from "element-resize-detector"
  • 1

使用:

        let myChart = elementResizeDetectorMaker();
        myChart.listenTo(this.$refs.chartDom, () => {
          this.$nextTick(() => {
            this.echartsInstance.resize();
          });
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我们在创建echarts实例的时候,使用即可,全部代码如下:

<!--
 * @Descripttion: 
 * @version: 
 * @Author: ZhangJunQing
 * @Date: 2022-06-08 16:01:36
 * @LastEditors: ZhangJunQing
 * @LastEditTime: 2022-08-10 17:38:41
-->
<template>
  <div class="chart" ref="chartDom"></div>
</template>

<script>
import elementResizeDetectorMaker from "element-resize-detector"
export default {
  props: {
    option: {
      type: Object,
      required: true,
      default: {},
    },
  },
  data() {
    return {
      echartsInstance: null,
    };
  },
  methods: {
    init() {
      if (!this.echartsInstance) {
        let charts = this.$refs.chartDom;
        this.echartsInstance = this.$echarts.init(charts);
        let myChart = elementResizeDetectorMaker();
        myChart.listenTo(this.$refs.chartDom, () => {
          this.$nextTick(() => {
            this.echartsInstance.resize();
          });
        });
      }
      // this.echartsInstance.showLoading({
      //       text: '暂无数据',
      //       showSpinner: false,
      //       textColor: '#646464',
      //       maskColor: 'rgba(255, 255, 255, 1)',
      //       fontSize: '16px',
      //       fontWeight: 'bold',
      //     })
      this.echartsInstance.setOption(this.option);
      // this.echartsInstance.hideLoading()
    },
  },
  watch: {
    option: {
      handler(newOption) {
        this.echartsInstance.clear();
        this.echartsInstance.resize();
        this.echartsInstance.setOption(newOption);
      },
      deep: true
    },
  },
  mounted() {
    this.init();
  },
};
</script>

<style lang="less" scoped>
.chart {
  // width: 300px;
  // height: 300px;
  width: 100%;
  height: 100%;
}
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

将elementResizeDetectorMaker的实例函数,变成防抖即可:

 myChart.listenTo(this.$refs.chartDom,
          () => {
            this.debounceFun(() => {
              this.echartsInstance && this.$nextTick(() => {
                this.echartsInstance.resize();
              })
            }, 18)
          }
        );
      }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

debounceFun

/**
 * @param {函数} fn
 * @param {防抖时间间隔} wait
 */
//防抖函数
export const debounce = () => {
    let timer = null;
    const newDebounce = function (fn, wait, ...args) {
        return new Promise((resolve, reject) => {
            if (timer !== null) {
                clearTimeout(timer);
            }
            timer = setTimeout(_ => {
                try {
                    resolve(fn(...args));
                } catch (e) {
                    reject(e);
                }
            }, wait);
        });
    };
    return newDebounce;
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

防抖函数使用:

  data() {
    return {
      debounceFun: debounce(),
      echartsInstance: null,
    };
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

改造之后的全部代码:
main.js

import elementResizeDetectorMaker from "element-resize-detector"
Vue.prototype.$erd = elementResizeDetectorMaker();
  • 1
  • 2

char:

<!--
 * @Descripttion: 
 * @version: 
 * @Author: ZhangJunQing
 * @Date: 2022-06-08 16:01:36
 * @LastEditors: ZhangJunQing
 * @LastEditTime: 2022-08-10 17:38:41
-->
<template>
  <div class="chart" ref="chartDom"></div>
</template>

<script>
// debounce
/**
 * @param {函数} fn
 * @param {防抖时间间隔} wait
 */
//防抖函数
/**
export const debounce = () => {
    let timer = null;
    const newDebounce = function (fn, wait, ...args) {
        return new Promise((resolve, reject) => {
            if (timer !== null) {
                clearTimeout(timer);
            }
            timer = setTimeout(_ => {
                try {
                    resolve(fn(...args));
                } catch (e) {
                    reject(e);
                }
            }, wait);
        });
    };
    return newDebounce;
};
 */

// this.$erd
/**
 * import elementResizeDetectorMaker from "element-resize-detector"
 * Vue.prototype.$erd = elementResizeDetectorMaker();
 */
import { debounce } from '@/utils/ToolFunctions'
export default {
  props: {
    option: {
      type: Object,
      required: true,
      default: {},
    },
  },
  data() {
    return {
      debounceFun: debounce(),
      echartsInstance: null,
    };
  },
  methods: {
    init() {
      if (!this.echartsInstance && !this.$echarts.getInstanceByDom(this.$refs.chartDom)) {
        let charts = this.$refs.chartDom;
        this.echartsInstance = this.$echarts.init(charts);

        // let myChart = ;
        // if (myChart == null) {
        //   myChart = this.$echarts.init(charts);
        //   this.echartsInstance = this.$echarts.init(charts);
        // }


        this.$erd.listenTo(this.$refs.chartDom,
          () => {
            this.debounceFun(() => {
              this.echartsInstance && this.$nextTick(() => {
                this.echartsInstance.resize();
              })
            }, 18)
          }
        );
      }
      this.echartsInstance.hideLoading()
      // this.echartsInstance.showLoading({
      //       text: '暂无数据',
      //       showSpinner: false,
      //       textColor: '#646464',
      //       maskColor: 'rgba(255, 255, 255, 1)',
      //       fontSize: '16px',
      //       fontWeight: 'bold',
      //     })
      this.echartsInstance.setOption(this.option);
      // this.echartsInstance.hideLoading()
    },
  },
  watch: {
    option: {
      handler(newOption) {
        // 显示暂无数据
        if (newOption.error) {
          // 实例生成
          if (this.echartsInstance) {
            this.echartsInstance.clear();
            this.echartsInstance.showLoading({
              text: '暂无数据',
              showSpinner: false,
              textColor: '#646464',
              maskColor: 'rgba(255, 255, 255, 1)',
              fontSize: '16px',
              fontWeight: 'bold',
            })
          } else {
            // 实例不存在
            this.$nextTick(() => {
              // 判断当前dom节点有没有 被 注册
              if (!this.$echarts.getInstanceByDom(this.$refs.chartDom)) {
                let charts = this.$refs.chartDom;
                this.echartsInstance = this.$echarts.init(charts);
              }
              this.echartsInstance.resize();
              this.echartsInstance.showLoading({
                text: '暂无数据',
                showSpinner: false,
                textColor: '#646464',
                maskColor: 'rgba(255, 255, 255, 1)',
                fontSize: '16px',
                fontWeight: 'bold',
              })
            })
          }
        } else {
          // 正常流程
          if (this.echartsInstance) {
            this.$nextTick(() => {
              this.echartsInstance.clear();
              this.echartsInstance.resize();
              this.echartsInstance.hideLoading()
              this.echartsInstance.setOption(newOption);
            })
          }
        }
      },
      deep: true,
      immediate: true
    },
  },
  mounted() {
    this.init();
  },
  destroyed() {
    this.echartsInstance = null
    this.$refs.chartDom && this.$erd.removeAllListeners(this.$refs.chartDom)
    this.$refs.chartDom && this.$refs.chartDom.clear();
  }
};
</script>

<style lang="less" scoped>
.chart {
  width: 100%;
  height: 100%;
}
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/223181
推荐阅读