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

 




 

posted @ 2020-05-06 18:04  leahtao  阅读(39701)  评论(2编辑  收藏  举报