• vue中使用echarts图表不显示解决办法


    在开发vue项目的时候遇到了一个问题,就是echarts图表不显示,但是写死数据的时候他会显示,想想这个可能就跟数据请求有关了,我是习惯了在mounted生命周期里面发送请求,mounted意思是页面已挂载完成,可以拿到dom节点了,这也说明echarts图表的dom结构也会在mounted的时候去挂载,然而这个时候我们的数据还没有请求回来,自然也就无法渲染出来了,我们需要在挂载之前就将数据请求回来,知道了这个相信大家也就知道怎么解决了,就是将数据请求放在created生命周期中。

    <div class="echarts">
          <newIncreaceEcharts class="newIncreaceEcharts"></newIncreaceEcharts>
          <PostRegion class="PostRegion" :postregiondata=postregiondata :regionlegend=regionlegend></PostRegion>
          <PostType class="PostType" :posttypedata=posttypedata :posttypelegend=posttypelegend></PostType>
          <post-salary class="PostSalary"  :salarydata=salarydata :salarylegend=salarylegend></post-salary>
        </div>
    created(){
          this.querydatastatics()
          this.postRegion()
          this.queryworktype()
          this.querysalary()
        },

     -------------------------------------------------------更新-------------------------------------------------------

    之前单纯的以为是请求数据的生命周期问题,确实也和这个有关,修改之后图表也显示了,但那是热更新,第一次创建实例的时候并不会显示,什么问题呢?

    在网上搜到两个答案,一个是用 $nextTick方法,让它在下一个事件队列中去渲染。(链接:https://www.jianshu.com/p/bfd940c31493  https://blog.csdn.net/alisa_lisa/article/details/88802471

    一个是用watch进行了监听,(链接:https://blog.csdn.net/qq_29918313/article/details/90267595

    我试了这两种方式都不好使,估计是写法和人家的不同,很苦恼,找了一天的bug,但我肯定这和数据请求数据与渲染的顺序有关,于是尝试在父组件传数据给子组件之前进行了判断。让它有数据 了再去渲染echarts图表。代码如下:

       <newIncreaceEcharts
            class="newIncreaceEcharts"
            v-if="increasedata.length > 0"
            :increasedlegend="increasedlegend"
            :increasedata="increasedata"
            :xAxisdata="xAxisdata"
          ></newIncreaceEcharts>
          <PostRegion
            class="PostRegion"
            v-if="postregiondata.length > 0"
            :postregiondata="postregiondata"
            :regionlegend="regionlegend"
          ></PostRegion>
          <PostType
            class="PostType"
            v-if="posttypedata.length > 0"
            :posttypedata="posttypedata"
            :posttypelegend="posttypelegend"
            
          ></PostType>
          <post-salary
            class="PostSalary"
            v-if="salarydata.length > 0"
            :salarydata="salarydata"
            :salarylegend="salarylegend"
          ></post-salary>

    v-if后面的数据是父组件需要传递给子组件的数据,判断有数据了再让这个子组件进行渲染,这样问题就完美解决了。

    但我还是想知道上面两种方法的原理,这个真的就是源码理解能力了,有时间了研究一下,再来补充。

    ------------------------------------------------------更新------------------------------------------------------------

    上面的第一个方法确实可以让图表在第一次实例化的时候显示出来,但是我们的图表是需要改变区域动态加载数据显示的,如下图:

    每次选择不同的区域后台返回的数据是不同的,但是页面并不会刷新,我以为是子组件没有观测到数据的变化,所以就给每个子组件加了watch监听数据的变化

    methods: {
         
        newincreacepie() {
          console.log(this.increasedata);
          var linechart = this.$echarts.init(this.$refs.newincreace);
          linechart.setOption({
          title: {
                text: "新增岗位趋势",
                left: '20px',
              top: '20px',
            },
            tooltip: {
              trigger: "axis",
              axisPointer: {
                type: "cross",
                label: {
                  backgroundColor: "#6a7985",
                },
              },
            },
            legend: {
              top: '20px',
              data: this.increasedlegend, //请求回来的数据
            },
            toolbox: {
              feature: {
                saveAsImage: {},
              },
            },
            grid: {
              left: "3%",
              right: "4%",
              bottom: "3%",
              containLabel: true,
            },
            xAxis: [
              {
                type: "category",
                boundaryGap: false,
                data: this.xAxisdata, //请求回来的数据
              },
            ],
            yAxis: [
              {
                type: "value",
              },
            ],
            series: this.increasedata, //请求回来的数据
          });
        },
    
      },
      
      watch:{
        increasedata:{
            handler(newValue, oldValue) {
              // alert('新增数据监听')
            if(oldValue != newValue) {
              this.newincreacepie()
            }
          },
          deep: true
        }
      },

    结果只有第一个图表可以更新,但是后面三个都还是没有更新,检查了子组件的数据,发现子组件的数据并没有变化,这个watch监听的时候发现新旧数据一样也就不会更新视图,所以就要看看父组件是怎么传值给子组件的。

    <newIncreaceEcharts
            class="newIncreaceEcharts"
            v-if="increasedata.length > 0"
            :increasedlegend="increasedlegend"
            :increasedata="increasedata"
            :xAxisdata="xAxisdata"
          ></newIncreaceEcharts>
          <PostRegion
            class="PostRegion"
            v-if="postregiondata.length > 0"
            :postregiondata="postregiondata"
            :regionlegend="regionlegend"
            ref="PostRegion"
          ></PostRegion>
          <PostType
            class="PostType"
            v-if="posttypedata.length > 0"
            :posttypedata="posttypedata"
            :posttypelegend="posttypelegend"
            
          ></PostType>
          <post-salary
            class="PostSalary"
            v-if="salarydata.length > 0"
            :salarydata="salarydata"
            :salarylegend="salarylegend"
          ></post-salary>

     

     //岗位区域分布
          postRegion(){
            console.log('postRegion开始执行')
            let formdata = {
              'region_code': this.regionId,
            }
            console.log(formdata)
            formdata = this.$Utils.demoRequest(JSON.stringify(formdata))
            this.$http.post('statistics/queryPostNumByRegion.do',formdata).then(res => {
              let data = JSON.parse(this.$Utils.demoResponse(res.data))
              console.log(data)
              let tempregion = []
              let tempregionlegend = []
              if(data.result == 0) {
                let statistics_data = data.statistics_data
                console.log(statistics_data)
                for(let i = 0; i < statistics_data.length; i++) {
                  var node = {};
                  node["value"] = statistics_data[i].totalCount;
                  node["name"] = statistics_data[i].labelDesc;
                  this.postregiondata.push(node);
                  this.regionlegend.push(statistics_data[i].labelDesc)
                }
              }
            })
          },
    postregiondata和regionlegend都是我要传给子组件的数据,在这里我是直接在遍历的时候将数据放进了要传的数组里面。在这种情况下父组件就观测不到数组的值是否发生变化,所以
    我就想到了用一个中间变量先接收传过来的值,然后再将这个中间变量赋值给要传递给子组件的这个数组。这样父组件就能观测到数据发生了变化,然后传给子组件。代码如下
     //岗位区域分布
          postRegion(){
            console.log('postRegion开始执行')
            let formdata = {
              'region_code': this.regionId,
            }
            console.log(formdata)
            formdata = this.$Utils.demoRequest(JSON.stringify(formdata))
            this.$http.post('statistics/queryPostNumByRegion.do',formdata).then(res => {
              let data = JSON.parse(this.$Utils.demoResponse(res.data))
              console.log(data)
              let tempregion = []
              let tempregionlegend = []
              if(data.result == 0) {
                let statistics_data = data.statistics_data
                console.log(statistics_data)
                for(let i = 0; i < statistics_data.length; i++) {
                  var node = {};
                  node["value"] = statistics_data[i].totalCount;
                  node["name"] = statistics_data[i].labelDesc;
                  console.log(node)
                  tempregion.push(node);
                  tempregionlegend.push(statistics_data[i].labelDesc)
                }
                this.postregiondata = tempregion
                this.regionlegend = tempregionlegend
              }
            })
            console.log('postRegion执行完毕')
          },

    总结:

    解决echarts图表不显示的问题:

    1.数据请求不能放在mounted生命周期中。

    2.图表挂载之前判断一下是否有数据,当数据请求回来以后再进行挂载。或者使用$nextTick方法,让图表在下一个tick或者本轮tick的微任务阶段挂载。

    3.父组件要使用中间变量的方式向子组件传递需要的数据。

    如上例子中方法

    4.在父组件数据发生改变后子组件要做到实时更新,就需要子组件用watch来监听数据的变化。而且对象类型和数组类型的监听方式不同

    数组类型:

     

    watch:{
        increasedata:{
            handler(newValue, oldValue) {
              // alert('新增数据监听')
            if(oldValue != newValue) {
              this.newincreacepie()
            }
          },
          deep: true
        }
      },

    数组中包含对象类型:

     

    watch:{
        postregiondata:{
            handler(newValue, oldValue) {
              for(let i = 0; i < newValue.length; i++) {
                if(oldValue[i].value != newValue[i].value) {
                   this.postregion()
                }
              }
          },
          deep: true
        }
      },

     文章推荐:https://www.jianshu.com/p/1b7e8a28d836

    https://www.cnblogs.com/goloving/p/9114389.html

    https://blog.csdn.net/chaitong2204/article/details/81976112?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase




    不积跬步无以至千里
  • 相关阅读:
    【转】[C# 基础知识系列]专题七:泛型深入理解(一)
    【转】[C# 基础知识系列]专题六:泛型基础篇——为什么引入泛型
    【转】[C# 基础知识系列]专题五:当点击按钮时触发Click事件背后发生的事情
    【转】[C# 基础知识系列]专题四:事件揭秘
    【转】[C# 基础知识系列]专题三:如何用委托包装多个方法——委托链
    Day 47 Django
    Day 45 JavaScript Window
    Day 43,44 JavaScript
    Day 42 CSS Layout
    Day 41 CSS
  • 原文地址:https://www.cnblogs.com/lyt0207/p/12838008.html
Copyright © 2020-2023  润新知