vue父组件异步获取数据传给子组件(vue父组件异步传值如何处理)

作者:电脑培训网 2024-04-29 01:41:11 739

在Vue中,父组件的异步数据通过props传递给子组件,但子组件无法接收。

vue中父组件异步数据通过props方式传递给子组件,子组件接收不到的问题

问题描述

vue父组件异步获取数据传给子组件(vue父组件异步传值如何处理)

在基于组件的开发中,经常会用到父子组件通信以及父子传输等数据操作。如果父组件的数据是通过发送请求从后端获取的异步数据,那么父组件会将这些数据传递给子组件。有时候,因为是异步数据,会出现父组件传递过来,但是子组件的mountedhook最初无法接收到的问题。本文记录了该问题的解决方案。

在讲这个问题之前,我们先回顾一下父子组件的生命周期。

父子组件生命周期执行顺序

加载渲染数据进程父组件

创建之前——

父组件已创建--

父组件beforeMount--

子组件beforeCreate--

创建子组件——

子组件beforeMount--

安装子组件--

父组件已安装--

更新渲染数据流程

父组件beforeUpdate--

子组件beforeUpdate--

子组件更新了——

父组件已更新--

销毁组件数据过程

父组件beforeDestroy--

子组件beforeDestroy--

子组件被毁——

父组件被破坏

可以理解为,在父组件的生命周期中,会首先检查子组件的生命周期是否已经完成。子组件的生命周期完成后,父组件的生命周期也会完成。

问题分析

我们来模拟一下父子组件的通信过程,写一个小demo。看看子组件中的mountedhook中能否接收到父组件传递过来的数据。

父组件代码

templatedivid='app'child:msg='msg'/child/div/templatescriptimportchildfrom'./views/child';exportdefault{name:'App',Components:{child,},data(){return{msg:'',//我们需要将父组件从界面获取到的数据存入data中的msg中,然后传递给子组件};},created(){//使用定时器模拟发送请求异步获取后端接口数据setTimeout(()={this.msg='666';},200);},};/脚本

子组件代码

templatedivh2{{msg}}/h2/div/templatescriptexportdefault{props:{msg:{type:String,default:''}},Mounted(){console.log('在挂载的钩子中收到',this.msg);},}/脚本

最终会在mounted的hook中实现,我们会发现无法打印,如下图

当然,如果同步数据传给子组件,子组件的mountedhook就可以接收并打印出来。这里就不演示了,因为我们做项目开发的大部分数据都是从后端接口获取的。异步数据。

因为父组件传递给子组件的数据在使用之前可能需要进行处理,所以需要在mountedhook中获取父组件传递的数据。那么,为什么这里的mountedhook中不能打印父组件传递过来的数据,但最终还是收到了props,最终渲染出页面呢?

原因简析

我们知道,mounted的hook默认只会执行一次。由于要到200毫秒后才能获取到数据,所以当执行子组件的mountedhook时,父组件传递过来的数据还没有获取到,但必须打印出来。this.msg的结果就出来了。这种情况下我们只能打印props中msg的默认值,即空字符串,所以打印的结果也是空字符串。例如,如果我们在子组件中打印this,我们就会知道this.msg是空字符串吗?

Mounted(){console.log('在挂载的钩子中收到',this.msg=='');},

打印结果图如下

但props可以等待并获取异步数据渲染。于是就出现了上面的结果。如果有问题,就解决问题。接下来我们就来说说这样的问题的解决办法。

方案一使用v-if控制子组件渲染的时机

思路其实很简单,就是初始没有获取到后端接口的异步数据时,不允许组件渲染,获取到后再次渲染组件。使用v-if='variable'来控制。最初将此变量设置为false。在这种情况下,子组件将不会被渲染。获取数据后,将此变量设置为true。这种情况下,组件就会去渲染,此时数据已经获取到了。这种情况下,会在子组件的mountedhook中获取父组件传递的异步数据。代码如下所示

父组件

templatedivid='app'child:msg='msg'v-if='isGetData'/child/div/templatescriptimportchildfrom'./views/child';exportdefault{name:'App',Components:{child,},data(){return{msg:'',isGetData:false//如果初始为false,则不会渲染相应的子组件};},created(){//使用定时器模拟发送请求异步获取后端接口的数据setTimeout(()={this.msg='666';this.isGetData=true//获取到数据后,设置isGetData为true,此时会渲染组件并传递数据。},200);},};/脚本

组件

这样子组件就不需要接触代码了,可以在父组件中进行控制。

不过这种方法有一个小缺点,就是最终的效果会显得组件生效有延迟。因为异步数据是从后端接口获取的,如果接口时间较长,最终效果渲染会比较慢,但是!一般情况下,后端接口速度会控制在几十到几百毫秒之内。一般情况下,界面会在几秒甚至几十秒内不会出现,所以缺陷并没有被隐藏,而且这种方法并不影响我们的使用。

方案二子组件使用watch监听父组件传递过来的数据

父组件

这样父组件就可以正常传递数据了。不需要代码处理。只需向子组件添加一个监听器即可。

组件

templatedivh2{{editMsg}}/h2/div/templatescriptexportdefault{props:{msg:{type:String,default:'',},},watch:{//监听到父组件传递过来的数据后,进行处理,//保存到data中,然后使用msg(newnew,oldold){console.log('listening',newnew,oldold);this.editMsg='---'+newnew+'---';},},data(){return{editMsg:'',};},};/脚本

看一下这个方法对应的效果图。

相关推荐