背景:
我需要在父组件里调用子组件中的computed值,搜索发现可以通过$refs获取到子组件里的内容,于是乎,下面是伪代码:
<template>
<children
v-if="show"
>{{ errorInfo }}</children>
</template>
<script>
export default {
data() {
return {
show: true
}
}
computed: {
errorInfo() {
if(this.$refs.children.errorInfo) {
return this.$refs.children.errorInfo
}
return ""
}
}
}
</script>
<template>
</template>
<script>
export default {
name: "children",
computed:{
errorInfo() {
return "我是子组件的错误信息"
}
}
}
</script>
但很奇怪,我在父组件的show中打印this.$refs.children为undifined,更别说获取子组件里的内容了,而且我不管怎么在子组件里change值,父组件都无法改变是否展示,去网上搜索了下资料发现:
问题:
在vue2中,this.$refs的触发时机是在mounted之后,但如果我在父组件最开始就想展示,
上网查了一遍资料后发现:this.$refs的访问时机应该是在mounted之后。
官网有这么一句话:关于 ref 注册时间的重要说明:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。
所以,在这个场景下,this.$refs.children之所以为undifined,主要是因为在mounted之后,但是computed的触发主要是根据数据是否变更进行计算的,它是在mounted之前执行的,也就是一开始computed获取到的$refs为空,又由于$refs是非响应式的,也就是组件渲染与否,不会影响到computed的变化,所以show值并不会发生变化。
解决措施:
可以通过watch实现,watch监听show值是否为true并更新parentErrorInfo字段值,computed里的errorInfo则会根据parentErrorInfo字段值的更新来动态的获取this.$refs,伪代码如下:
<template>
<children
v-if="show"
>{{ errorInfo }}</children>
</template>
<script>
export default {
data() {
return {
show: true,
parentErrorInfo: ""
}
},
computed: {
errorInfo() {
if(this.parentErrorInfo) {
return this.$refs.children.errorInfo
}
return ""
}
},
watch:{
show(newValue) {
if(newValue){
this.$nextTick(()=>{
this.parentErrorInfo = this.$refs.children.errorInfo
})
}
}
}
}
</script>