在vue中引用Echarts图表,动态渲染数据时一直不展示数据。父组件异步请求获取数据传给子组件,子组件接收的打印的真实的值却为初始值,如下所示
原因的话:加载渲染的时候,请求是一个异步的操作,子组件在拿到数据前就渲染了,子组件没有监控到值得变化
父子组件加载渲染过程:
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
昨天晚上遇到这个问题,在网上找了是下面三个方法:
上面三种方法的话:
这样的话,其实昨天就没解决这个问题,下班回去的时候换了一个思路想了这个问题,这个原因就是父组件异步请求没有更新子组件的数据值,其实我们可以手动的更新子组件的值,在父组件异步请求拿到数据时,在成功回调赋值的时候,手动的调用子组件的方法,并把数据当成参数传递过去,子组件的处理就是在该方法内手动的刷新对象的,今天早上上班按照该思路,发现可以解决这个问题。
下面就介绍一下vue父组件异步获取数据,子组件接收的值为空三种解决方法:
一:父组件异步获取数据,调用子组件方法重新赋值 【第二种方法不行,推荐使用该方法】
父组件
<template>
<div class="index">
//设置ref的值,下面调用
<ChartBasicLine :chartObj="chartRegUser" :ref="chartRegUser.type" />
div>
template>
<script>
import { getStatUser } from '@/api/data'
import ChartBasicLine from '@/components/Chart/ChartBasicLine'
export default {
components: {
ChartBasicLine
},
data() {
return {
chartRegUser: {
num: 0,
percent: '0.00%',
status: 0,
type: 'reg_user',
tips: '新增用户',
title: '新增用户(NU)',
link: '',
isShow: false,
xData: [],
yData: []
}
}
},
created() {
this.getStatUser()
},
methods: {
getStatUser() {
const _this = this
// 异步请求获取数据
getStatUser().then(res => {
if (res.code === 0) {
// 赋值
_this.$set(_this.chartRegUser, 'xData', res.data['x_data'])
_this.$set(_this.chartRegUser, 'yData', res.data['y_data'])
// 这里是调用子组件的refresh的方法
_this.$refs[_this.chartRegUser.type].refresh(res.data)
}
})
}
}
}
script>
子组件
<template>
<div class="ChartBasicLine">
<div
:ref="chartObj.type"
class="chart_show"
/>
div>
template>
<script>
export default {
name: 'ChartBasicLine',
props: {
chartObj: {
type: Object
}
},
data() {
return {
option: {
tooltip: {
trigger: 'axis'
},
grid: {
top: '22px',
left: '40px',
right: '30px'
},
xAxis: {
type: 'category'
},
yAxis: {
type: 'value'
},
series: [{
type: 'line'
}]
},
myChart: {}
}
},
mounted() {
this.showChart()
},
methods: {
showChart() {
this.myChart = this.$echarts.init(this.$refs[this.chartObj.type])
this.option.xAxis['data'] = this.chartObj.xData
this.option.series[0]['data'] = this.chartObj.yData
this.myChart.setOption(this.option)
},
/**
* 父组件给图表信息重新赋值,并重新刷新图表
*/
refresh(data) {
this.option.xAxis['data'] = data['x_data']
this.option.series[0]['data'] = data['y_data']
this.myChart.setOption(this.option)
}
}
}
script>
<style>
.ChartBasicLine .el-input {
margin-right: 0 !important;
}
style>
二:子组件内使用watch监控对象值变化时重新赋值【推荐】
子组件
<template>
<div class="ChartBasicLine">
<div
:ref="chartObj.type"
class="chart_show"
/>
div>
template>
<script>
export default {
name: 'ChartBasicLine',
props: {
chartObj: {
type: Object
}
},
data() {
return {
option: {
tooltip: {
trigger: 'axis'
},
grid: {
top: '22px',
left: '40px',
right: '30px'
},
xAxis: {
type: 'category'
},
yAxis: {
type: 'value'
},
series: [{
type: 'line'
}]
},
myChart: {}
}
},
watch: {
chartObj: { // 监控该变量,重新赋值并刷新图表
handler(newVal, oldVal) {
this.chartObj = newVal
this.showChart()
},
deep: true // 必须设置
}
},
mounted() {
this.showChart()
},
methods: {
showChart() {
this.myChart = this.$echarts.init(this.$refs[this.chartObj.type])
this.option.xAxis['data'] = this.chartObj.xData
this.option.series[0]['data'] = this.chartObj.yData
this.myChart.setOption(this.option)
}
}
}
script>
三:父组件内使用v-if渲染子组件【不推荐】
父组件
<template>
<div class="index">
// 通过v-if来控制子组件显示
<ChartBasicLine v-if="isShow" />
div>
template>
<script>
import { getStatUser } from '@/api/data'
import ChartBasicLine from '@/components/Chart/ChartBasicLine'
export default {
components: {
ChartBasicLine
},
data() {
return {
chartRegUser: {
num: 0,
percent: '0.00%',
status: 0,
type: 'reg_user',
tips: '新增用户',
title: '新增用户(NU)',
link: '',
isShow: false,
xData: [],
yData: []
},
isShow: false // 控制子组件是否展示
}
},
created() {
this.getStatUser()
},
methods: {
getStatUser() {
const _this = this
getStatUser().then(res => {
if (res.code === 0) {
_this.$set(_this.chartRegUser, 'xData', res.data['x_data'])
_this.$set(_this.chartRegUser, 'yData', res.data['y_data'])
// 异步请求获取数据,展示子组件
_this.isShow = true
}
})
}
}
}
script>