父子组件通过props传参,子组件在created中接收props不能实时更新
问题背景:父组件为index.vue, 两个子组件为home-header.vue和home-sidebar.vue。现在需要在父组件中请求完数据后,两个子组件才去发生请求数据。解决方案一:在父组件index.vue中定义两个变量,用来确定父组件中的请求是否完毕,然后在子组件中使用v-if:index.vue:<template><div id="index"><ho
问题背景:父组件为index.vue, 两个子组件为home-header.vue和home-sidebar.vue。现在需要在父组件中请求完数据后,两个子组件才去发生请求数据。
解决方案一:
在父组件index.vue
中定义两个变量,用来确定父组件中的请求是否完毕,然后在子组件中使用v-if
:
index.vue
:
<template>
<div id="index">
<home-header v-if="homeHeader" />
<home-sidebar v-if="homeSider" />
</div>
</template>
...
data() {
return {
homeHeader: false,
homeSider: false
}
},
axios请求成功后才设置: homeHeader 和 homeSider = true
这时是可以解决问题的,但是由于header和sider的背景是黑色,在该组件未显示的时候,会出现白色的过渡,页面看上去效果不好。所以就有了下面思考:
方案二:(有问题)
在父组件index
中将表示axios是否请求完成的homeHeader
和 homeSider
通过props
传递给子组件,然后在子组件中接收到值后再去发生请求。
父组件index
<template>
<div id="index">
<home-header :isShow="homeHeader" />
<home-sidebar :isShow="homeSider" />
</div>
</template>
...
data() {
return {
homeHeader: false,
homeSider: false
}
},
axios请求成功后才设置: homeHeader 和 homeSider = true
子组件:home-header
(只拿一个举例)
props: {
isShow: {
type: Boolean,
default: false
}
},
created() {
// 请求版本号信息
if (this.isShow) {
getVersion().then(res => {
if (res.data) {
this.version = res.data
}
})
}
},
这时出现问题,初次进入页面子组件的请求并不会执行,但是在刷新浏览器后就会执行。
寻找原因:
为了寻找原因,我又创建了一个新的demo,问题的本质一样
父组件:index.vue
:
<template>
<div id="index">
<props-test :isShow="isShow" />
</div>
</template>
<script>
import PropsTest from '@/components/PropsTest'
export default {
name: 'Index',
components: {
PropsTest
},
data() {
return {
isShow: false
}
},
created() {
setTimeout(() => (this.isShow = true), 5000)
}
}
</script>
<style scoped></style>
子组件:Propstest.vue
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
name: '',
props: {
isShow: {
type: Boolean,
default: false
}
},
data() {
return {
message: 'isShow为false时显示'
}
},
created() {
if (this.isShow) {
this.message = 'isShow为true时显示'
}
}
}
</script>
<style scoped></style>
初次进入页面的显示效果:
可以观察到,子组件中的isShow
已经变为了true
但是message
的值并没有变。
其实,通过vuetools可以看到,isShow
的值确实已经发生了改变,但message
的数据并没有更新。这是因为在页面生成后,父组件和子组件都已经挂载完毕,但这时父组件中的异步请求还没有完成。所以初次进入页面时,isShow为false,子组件执行created钩子时发现isShow为false,就不会去改变message的值。然后,等待父组件中的异步请求完毕后,isShow变为了true,并且传递到子组件中,这时,可以在tools中观察到isShow发生了变化,但是messaeg并没有改变。这是因为此时子组件的created钩子并不会触发
可以在子组件created
中打印一下isShow
,发现它只打印了一次,而且是刚进入页面就打印了。这也说明created
钩子只触发了一次:
怎么解决这个问题呢
使用watch
监听props
的变化
官方文档中有对用watch
监听props
变化的介绍,点击此处。
和监听data
中的数据不一样,监听props
需要这样:
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
name: '',
props: {
isShow: {
type: Boolean,
default: false
}
},
data() {
return {
message: 'isShow为false时显示'
}
},
watch: {
isShow: {
handler(newValue) {
if (newValue) {
this.message = 'isShow为true时显示'
}
},
immediate: true
}
}
// created() {
// console.log('this.isShow', this.isShow)
// if (this.isShow) {
// this.message = 'isShow为true时显示'
// }
// }
}
</script>
<style scoped></style>
这时打开页面:
到此,问题终于解决。
方案二(修复)
使用watch
来监听 props
watch: {
isShow: {
handler(newValue) {
if (newValue) {
this.requestBriefInfo()
}
},
immediate: true
}
},
更多推荐
所有评论(0)