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

 




 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM