VUE父组件异步获取数据,子组件接收的值为空的问题
作者:修复BUG中
这篇文章主要介绍了VUE父组件异步获取数据,子组件接收的值为空的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
在vue中引用Echarts图表,动态渲染数据时一直不展示数据。
父组件异步请求获取数据传给子组件,子组件接收的打印的真实的值却为初始值,如下所示
- 父组件
- 子组件
原因的话:
加载渲染的时候,请求是一个异步的操作,子组件在拿到数据前就渲染了,子组件没有监控到值得变化
父子组件加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
昨天晚上遇到这个问题,在网上找了是下面三个方法:
- 在子组件用watch监控父组件传递过来值得变化,设置deep:true【deep官方定义:为了发现对象内部值的变化,可以在选项参数中指定 deep: true。注意监听数组的变更不需要这么做。】
- 在父组件使用v-if,当请求结束之后,改变v-if内变量的值,加载子组件
- 使用vuex全局状态管理,这个没尝试
上面三种方法的话:
- 第一种是最简洁明了的,但是昨天晚上第一种方法一直不成功,可能是语法写错了,今天早上上班试了一下才成功;
- 因为我们做的是数据展示,所以第二种就不适合我们的需求;
- 第三种的话我就没试,网上的解决流程感觉太麻烦了;
这样的话,其实昨天就没解决这个问题,下班回去的时候换了一个思路想了这个问题,这个原因就是父组件异步请求没有更新子组件的数据值,其实我们可以手动的更新子组件的值,在父组件异步请求拿到数据时,在成功回调赋值的时候,手动的调用子组件的方法,并把数据当成参数传递过去,子组件的处理就是在该方法内手动的刷新对象的,今天早上上班按照该思路,发现可以解决这个问题。
下面就介绍一下vue父组件异步获取数据,子组件接收的值为空三种解决方法:
1.父组件异步获取数据,调用子组件方法重新赋值 【第二种方法不行,推荐使用该方法】
- 父组件
<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>
2.子组件内使用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>
3.父组件内使用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>
VUE中数组赋空值注意事项
在js或者Vue中,给数组赋空值不可以直接赋空值,例如:
var list = {a:'12',b:'34'};// 创建一个数组 list = [];// 数组赋空值
否则会在再次赋值的时候报错
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。