问题描述
父组件的数据是请求后台所得,因为是异步数据,就会出现,父组件的值传递过去了,子组件加载不到,拿不到值的问题。
下面从同步数据传递和异步数据传递开始论述问题
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监听父组件传递过来的数据。
这种方式父组件正常传递数据即可,不要做什么代码处理,只要在子组件中加一个监听即可。