vue父组件异步传递prop到子组件echarts画图问题踩坑总结
问题描述
在父组件使用定义好的echarts饼状图组件,通过父组件向子组件传递id和data,子父组件中data定义的数据,子组件可以接收到,图标正常显示;通过axios请求的后台数据,赋给data定义的数据对象,则子组件获取到的还是data之前定义好的数据,赋值无意义
思考 父组件传递prop就是渲染时传递
所以考虑到父组件传递prop,子组件mounted阶段就是渲染时传递,而不是赋值时传递的,所以总是传递的data()里面初始化的数据。所以通过父组件去调用子组件方法去画图也行不通。
那么我就可以给子组件加个判断 v-if 条件,当父组件从后台异步取到数据后,并且赋值给prop后,让flag = true再去渲染子组件,那么此时传递给子组件的prop就是异步获取到数据之后的值,图形就正常展示出来了。
解决方案
给子组件加个判断 v-if 条件,当父组件从后台异步取到数据后,并且赋值给prop后,让flag = true再去渲染子组件
代码如下
父组件
<template>
<div class="czfx d-flex-wrap">
<el-row class="" :gutter="30">
<el-col :span="6">
<div>
<div class="tit">总体产值</div>
<div class="con">
<PieChart
v-if="flag.baizhang"
style="min-height: 1.6rem"
height="100%"
width="100%"
id="allchart"
:datas="allData"
></PieChart>
</div>
</div>
</el-col>
<el-col :span="6">
<div>
<div class="tit">100章产值</div>
<div class="con">
<PieChart
v-if="flag.baizhang"
style="min-height: 1.6rem"
height="100%"
width="100%"
id="100chart"
:datas="oneData"
></PieChart>
</div>
</div>
</el-col>
<el-col :span="6">
<div>
<div class="tit">200章产值</div>
<div class="con">
<PieChart
v-if="flag.baizhang"
style="min-height: 1.6rem"
height="100%"
width="100%"
id="200chart"
:datas="twoData"
></PieChart>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { apiBaizhang, apiProgress } from "@/request/api";
import PieChart from "@/components/chart/pie";
export default {
name: "App",
components: {
PieChart,
BarChart,
XbarChart,
BarlineChart,
MoreBarChart,
},
data() {
return {
flag: {
baizhang: false, //是否开始渲染子组件
},
allData: {
title: "总体产值",
data: [
{ name: "已完成", value: 1600 },
{ name: "未完成", value: 180 },
],
},
oneData: {
title: "100章产值",
data: [
{ name: "已完成", value: 26 },
{ name: "未完成", value: 10 },
],
},
twoData: {
title: "200章产值",
data: [
{ name: "已完成", value: 26 },
{ name: "未完成", value: 1 },
],
},
};
},
mounted() {
let that = this;
that.getBaizhangData();
},
methods: {
getBaizhangData() {
let that = this;
apiBaizhang().then((res) => {
if (res.code == "200" || res.code == 200) {
let datas = res.result;
that.allData = datas.all;
that.oneData = datas[100];
that.twoData = datas[200];
that.threeData = datas[300];
that.fourData = datas[400];
that.fiveData = datas[500];
that.sixData = datas[600];
that.sevenData = datas[700];
that.flag.baizhang = true;
}
});
},
},
};
</script>
子组件
<template>
<div :id="id" :style="{ height: height, width: width }" :data="datas"></div>
</template>
<script>
const echarts = require('echarts')
import $ from 'jquery'
export default {
props: {
height: '',
width: '',
id: '',
datas: Object,
},
data() {
return {}
},
mounted() {
let that = this
that.initPieChart()
console.log('===',that.datas)
},
methods: {
initPieChart() {
let that = this
var colors = [
{
borderColor: 'rgba(74,237,255,1)',
start: 'rgba(74,237,255,0.1)',
end: 'rgba(74,237,255,0.8)',
},
{
borderColor: 'rgba(255,76,80,1)',
start: 'rgba(255,76,80,0.1)',
end: 'rgba(255,76,80,0.8)',
},
{
borderColor: 'rgba(66,255,186,1)',
start: 'rgba(66,255,186,0.1)',
end: 'rgba(66,255,186,0.8)',
},
{
borderColor: 'rgba(241,205,62,1)',
start: 'rgba(241,205,62,0.1)',
end: 'rgba(241,205,62,0.8)',
},
]
var fontsize = {
xs: 20,
small: 24,
mid: 36,
big: 48,
}
var myChart = echarts.init(document.getElementById(this.id), 'shine')
let dataArr = []
console.log(that.datas)
that.datas.data.forEach(function (item, idx) {
dataArr.push({
value: item.value,
name: item.name,
itemStyle: {
normal: {
color: colors[idx].end,
},
},
})
})
let option = {
tooltip: {
trigger: 'item',
formatter: '{b} : {c} ({d}%)',
textStyle: {
fontSize: fontsize.small,
},
},
title: [
{
text: that.datas.title,
top: '55%',
left: 'center',
textStyle: {
fontSize: fontsize.small,
color: '#10c685',
fontWeight: 700,
},
},
],
legend: {
//orient:'vertical', //图例的布局朝向
x: 'center', //图例的位置--离左边的距离
y: 'top', //图例的位置--离上边的距离
itemGap: 16, //图例的间隔
data: that.datas.data,
textStyle: {
color: '#00BEF0',
fontSize: fontsize.small,
},
formatter: function (name) {
var total = 0
var target
for (var i = 0, l = that.datas.data.length; i < l; i++) {
total += that.datas.data[i].value
if (that.datas.data[i].name == name) {
target = that.datas.data[i].value
}
}
return name + ' ' + target //((target / total) * 100).toFixed(2) + '%'
},
},
toolbox: {
show: true,
feature: {
mark: { show: true },
dataView: { show: false, readOnly: false },
magicType: {
show: true,
type: ['pie', 'funnel'],
},
restore: { show: false },
saveAsImage: { show: false },
},
},
calculable: true,
series: [
{
type: 'pie',
radius: ['45%', '60%'],
center: ['50%', '60%'],
hoverAnimation: false,
labelLine: {
normal: {
show: false,
length: 5,
length2: 5,
},
emphasis: {
show: false,
},
},
data: dataArr,
label: {
normal: {
show: false,
formatter: '{d}%',
fontSize: fontsize.xs,
},
},
},
],
}
window.onresize = function () {
myChart.resize()
}
myChart.setOption(option)
},
},
}
</script>