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