背景
在vue项目中,父组件一些数据是通过接口异步获取的,然后子组件通过Props 父子之间通信,父组件和子组件加载的顺序
父beforeCreate=>父created=>父beforeMount=>父beforeCreate=>子created=>子beforeMount=>子mounted=>父mounted
由于父组件的数据是异步的过来的,可会出现父组件还没有获取到数据,子组件就已经加载完毕。导致子组件没有得到最新数据。
模拟异常代码
父组件
异步组件渲染vue1.x版本
{{batchId}}
子组件
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
props: ['name'],
template: '#displayBatch',
data: function () {
return {
count: 0,
info:""
}
},
ready: function () {
this.$nextTick(function () {//节点最新更新后执行
this.loadData();
console.log("info" + this.info)
})
},
methods: {
loadData: function() {
setTimeout(() => {
this.info = this.name + "uuuuu";
console.log("info" + this.info)
},100)
}
}
})
效果:子组件没有显示abcuuuuu;而是nulluuuuu
解决方案
Vue1.x版本
- v-if
{{batchId}}
这个可以说是很经典的一个办法,但是会有展示上的问题,即dom结构会先消失而后重新渲染
并不算是一个完美的解决方案,所以暂时Pass掉
- 异步组件
Vue.component('button-counter', function(resolve, reject) {
setTimeout(() => {
resolve({
props: ['name'],
template: '#displayBatch',
data: function () {
return {
count: 0,
info:""
}
},
ready: function () {
this.$nextTick(function () {
this.loadData();
console.log("info" + this.info)
})
},
methods: {
loadData: function() {
setTimeout(() => {
this.info = this.name + "uuuuu";
console.log("info" + this.info)
},50)
}
}
})
}, 310);//这个时间理论上可以定义0;因为ajax请求时微观任务,setTimeout是宏观任务;这里为了方便测试设置比300大 就可以
})
- 监听watch;
两个方式:子组件可以监听,父组件也可以监听
子组件实现方式
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
props: ['name'],
data: function () {
return {
count: 0,
info:""
}
},
watch:{
name: function(newVal,oldVal) {
console.log(newVal)
if(newVal) {
// console.log(this.$refs.testbutton.loadData());
this.loadData();
}
}
},
methods: {
loadData: function() {
setTimeout(() => {
this.info = this.name + "uuuuu";
},100)
}
},
template: ''
})
父组件实现方式
watch: {
batchId: function(newVal, oldVal) {
if(newVal) {
this.$refs.testbutton.loadData();
}
}
},
- forceUpdate 方法
父组件
watch: {
batchId: function(newVal, oldVal) {
if(newVal) {
// this.$refs.testbutton.loadData();
this.$refs.testbutton.$forceUpdate();
}
}
},
子组件
updated: function(){
console.log("updated")
this.loadData();
},
扩展
咋样友好重新渲染组件?
http://www.muzhuangnet.com/show/54308.html
总结
解决问题本质,就是让子组件在父组件数据变化时,要让子组件感知到,强制渲染子组件;
使用v-if 效果最不好,不推荐使用。(但是这个方法是不要动之前已经封装好的子组件)