学习笔记230827--vue项目中,子组件拿不到父组件异步获取数据的问题
🧋 问题描述
父组件的数据是请求后台所得,因为是异步数据,就会出现,父组件的值传递过去了,子组件加载不到,拿不到值的问题。
下面从同步数据传递和异步数据传递开始论述问题
🧋🧋1. 父组件传递的是同步数据
-
父组件
<template> <div class="parent"> <div class="child"> <props-children :data="dataJson"></props-children> </div> <input type="text" v-model="dataJson"/> </div> </template> <script> import propsChildren from '../../component/props/props_children.vue' export default { components: { propsChildren }, data(){ return{ dataJson:"初始化数据" } }, created(){ console.log('父created',this.dataJson) }, beforeuUpdate(){ console.log('父beforeupdated',this.dataJson) }, updated(){ console.log('父updated',this.dataJson) }, beforeDetroy(){ console.log('父beforeDetroy',this.dataJson) }, detroyed(){ console.log('父detroyed',this.dataJson) } } </script> <style scoped> .child{ width:600px; height:600px; background:#eee; } </style>
-
子组件
<template> <div> 我是子组件<br><br><br> 获取到父组件数据:{{data}}<br><br><br> <input type="text" v-model="data"/> </div> </template> <script> export default { mounted(){ console.log('子组件拿到数据',this.data) }, props:{ data:{ default:"", require:true, type:String } }, created(){ console.log('子created',this.data) }, beforeUpdate(){ console.log('子beforeupdated',this.data) }, updated(){ console.log('子updated',this.data) }, beforeDetroy(){ console.log('子beforeDetroy',this.data) }, detroyed(){ console.log('子detroyed',this.data) } } </script> <style> </style>
如图所示:
-
在created阶段,父组件的初始化数据就已经传递给了子组件的props
-
在created阶段,把获取的同步数据赋值给初始化数据,不会触发update钩子函数,子组件加载也能拿到数据
-
父组件更新数据(触发update),子组件也会同步更新,但是先更新的是子组件里的数据
-
子组件去更新props里的数据,父组件不但接收不到,而且还会报错
父子组件声明周期执行顺序
加载渲染数据过程
父:beforeCrete --> 父:created --> 父:beforeMount --> 子:beforeCreate --> 子:created --> 子:beforeMount --> 子:mounted --> 父:mounted
更新渲染数据过程
父:beforeUpDate --> 子:beforeUpdate --> 子:updated --> 父:updated
销毁组件数据过程
父:beforeDestroy --> 子:beforeDestroy --> 子:destroyed --> 父:detroyed
但是,如果父组件获得是后台请求的异步数据就会出现问题。
🧋🧋 2.父组件传递的是异步数据
- 父组件
<template>
<div class="parent">
<div class="child">
<props-children :data="dataJson"></props-children>
</div>
<input type="text" v-model="dataJson"/>
</div>
</template>
<script>
import propsChildren from '../../component/props/props_children.vue'
export default {
components: { propsChildren },
data(){
return{
dataJson:"初始化数据"
}
},
created(){
// 模拟获取后台异步数据
setTimeout(()=>{
this.dataJson="父组件数据"
},200)
console.log('父created',this.dataJson)
},
beforeUpdate(){
console.log('父beforeupdated',this.dataJson)
},
updated(){
console.log('父updated',this.dataJson)
},
beforeDetroy(){
console.log('父beforeDetroy',this.dataJson)
},
detroyed(){
console.log('父detroyed',this.dataJson)
}
}
</script>
<style scoped>
.child{
width:600px;
height:300px;
background:#eee;
}
</style>
- 子组件
<template>
<div>
我是子组件<br><br><br>
获取到父组件数据:{{data}}<br><br><br>
<input type="text" v-model="data"/>
</div>
</template>
<script>
export default {
mounted(){
console.log('子组件拿到数据',this.data)
},
props:{
data:{
default:"",
require:true,
type:String
}
},
created(){
console.log('子created',this.data)
},
beforeUpdate(){
console.log('子beforeupdated',this.data)
},
updated(){
console.log('子updated',this.data)
},
beforeDetroy(){
console.log('子beforeDetroy',this.data)
},
detroyed(){
console.log('子detroyed',this.data)
}
}
</script>
<style>
</style>
【产生问题的原因】
父组件异步获取后台数据, 这时候加载渲染数据生命周期已经走完,只能更新数据,触发更新渲染生命周期,所以子组件加载时,永远只能拿到父组件的初始数据,拿不到父组件更新后的数据,但是,但是props是可以等的,页面是可以拿到异步的数据渲染的,所以就出现如上所示 的结果。
🧋解决问题
如何子组件加载获取不到父组件异步获取数据的问题
-
方案1:使用v-if控制子组件渲染的时机,父组件拿到后台异步数据后,再渲染子组件,加载子组件的时候就能得到父组件 的异步数据。
-
方案2:子组件使用watch监听父组件传递过来的数据。
这种方式父组件正常传递数据即可,不要做什么代码处理,只要在子组件中加一个监听即可。
🧋问题总结
子组件props如果绑定动态数据,默认只在加载时传递,也就是说只传一次。props绑定视图层,可以传多次。父组件created赋值同步数据不会触发updated,同步数据可以在created时就传递给子组件。父组件赋值异步数据,触发update,子组件也会在update才能拿到数据,所以加载时只能拿到父组件的初始化数据。