在Vue中,父组件的异步数据通过props传给子组件,子组件接收不到的问题
问题描述组件开发中经常会用到父子组件之间的通信。父组件的数据是通过发送请求从后端获取的异步数据。父组件传递这个数据给子组件的时候,因为是异步数据,所以父组件会传递,但是子组件挂载的hook最初是一个不能接受的问题。本文记录了此问题的解决方案。在说这个问题之前,我们先来回顾一下父子组件的生命周期。父子组件的生命周期是顺序执行的。子组件创建-->子组件beforeMount-->子组件挂载-->父组件挂载-->更新渲染数据处理父组件beforeUpdate-->子组件beforeUpdate-->子组件更新-->父组件更新-->销毁组件数据处理父组件beforeDestroy-->子组件beforeDestroy-->子组件销毁-->父组件销毁可以这样理解。在父组件的生命周期中,会先检查子组件的生命周期是否已经结束。父组件的生命周期只有在子组件的生命周期结束后才会被跟随。问题分析下面模拟一下父子组件通信的过程,写一个小demo。在子组件父组件代码
子组件代码
{{msg}}
最终会在mountedhook中执行,我们会发现打印不出来,如下图。当然,如果同步数据传递给子组件,子组件的mountedhook可以接收并打印出来,这里就不演示了,因为我们做项目开发的数据大部分是从后端接口获取的异步数据输出。因为父组件传递给子组件的数据在使用前可能需要处理,所以需要在mountedhook中获取父组件传递的数据。那么,为什么父组件传递过来的数据在mountedhook中打印不出来,却最终接收到props,最终渲染页面呢?原因分析我们知道mountedhook默认只会执行一次。由于要等到200毫秒后才能获取到数据,所以当子组件的mountedhook执行时,还没有获取到父组件传过来的数据,但是必须打印出this.msg的结果。在这种情况下,我们只能在props中打印msg默认的空串,所以打印出来的结果是一个空串。比如我们在子组件中这样打印你就会知道this.msg是不是空串},打印结果如下但是props可以等待,是获取异步数据渲染。于是出现了上面的结果,有问题解决问题。接下来说说这个问题的解决方法。思路是用v-if来控制子组件渲染的时机。思路其实很简单,就是一开始没有获取到后端接口。当数据是异步的时候,不允许组件渲染,组件接收到就渲染。使用v-if="variable"来控制,一开始让这个变量为false,这样子组件就不会渲染,等拿到数据的时候,让这个变量为true,这样组件就会渲染去渲染,此时数据已经拿到了。在这种情况下,父组件传递的异步数据将在子组件的挂载钩子中获取。代码如下父组件
这样子组件不需要移动代码就可以在父组件中控制,但是这种方式有一个小缺点,就是最终效果会出现延迟之前组件出现。因为异步数据是从后端接口获取的,如果接口耗时较长,最终效果渲染会比较慢,但是!!!一般情况下,后台的接口速度会控制在几十到几百毫秒。一般情况下,几秒甚至几十秒都不会出现界面,所以并没有隐藏破绽。该方法不影响我们使用该方案的第二个子组件。使用watch监听父组件传过来的数据。这样父组件就可以正常传递数据了。无需代码处理。只需在子组件中添加一个监视器即可。子组件
{{editMsg}}
看一下这个方法对应的效果图就可以看到处理了parent组件传过来的数据。方案三:父子组件通信不使用props,比如使用eventbus、vuex。但是,一般情况下,父子组件通信使用的是props通信。因此,解决问题的方式是可选的。一种类型就可以了。