今天在改微信小程序的时候遇见一个比较有趣的问题。先上简版代码如下:
子组件用到了父组件传递过来的一个对象clientInfo,该对象是父组件异步获取的。
我们都知道子组件mounted是先于父组件的,因此子组件初次渲染时拿不到clientInfo,为了防止报错(TypeError: Cannot read property 'name' of null),我们通过v-if控制渲染时间,if 控制子组件初始化函数执行时间。
子组件挂载完成后,父组件还未挂载。所以组件数据回显的时候,在父组件
mounted
中获取api的数据,子组件的mounted
是拿不到的。
<template>
<view v-if="clientInfo">
<view class="bold u-font-16">
({{ clientInfo.code }}){{ clientInfo.name }}
</view>
</view>
</template>
<script>
export default {
props: ['clientInfo'],
mounted() {
if(this.clientInfo)
this.initData(this.clientInfo.id)
},
}
</script>
今天翻到这段代码,虽说是work的,但我想优化一下,思路是引入骨架屏,使前端展示友好一点,调整函数写法,使表达更优雅一点。
1、去除 v-if,给props设置default值
2、去除 mounted 中通过 if 控制初始化函数,让父组件通过 ref 在异步获取clientInfo后调用子组件初始化函数
父组件代码如下:
<template>
<view class="u-skeleton">
<view class="u-skeleton-rect">
<quick-metrics ref="metric" :clientInfo="clientInfo"></quick-metrics>
</view>
</view>
</template>
<script>
import quickMetrics from "@/components/customer/details/quick-metrics.vue";
export default {
components: {
quickMetrics,
},
mounted() {
this.initData()
},
data() {
return {
clientInfo:null,
}
},
methods: {
async initData(){
await this.getclientInfo();
this.$refs.metric.initData(this.clientInfo.id)
}
}
}
</script>
这里还有一个知识 , 空字符串和空对象触发不了default,null和undefined过不了requied:true。
vue中认为
""
/{}
等是初始化值了,所以传入值触发不了default
优化后子组件代码如下:
<template>
<view>
<view class="bold u-font-16">
({{ clientInfo.code }}){{ clientInfo.name }}
</view>
</view>
</template>
<script>
export default {
props: {
clientInfo:{
type:Object,
// required:true,
default:function(){
return {
id:'',
name:'',
code:'',
}
}
}
},
methods: {
initData(id){
...
}
}
}
</script>
由于vue不对null应用default,所以我们将父组件clientInfo改为初始值 undefined。
但还是报错,TypeError: Cannot read property 'name' of null。
我就很奇怪,那里来的null?
我在父组件用watch监听clientInfo,只有两个值,undefined和异步取得的值。
我又在子组件监听clientInfo,得到了undefined->null->父组件传过来的值。
众所周知,子组件并不能修改props值,所以那里冒出来一个null?
最后我找到了如下描述:
小程序端不支持更新数据的值为 undefined,框架内部将会替换为 null,需要自行绕过一下。
我晕(((φ(◎ロ◎;)φ))) 关于props还有疑问的,可以看看以下文章。
参考文章:
子组件Props的默认值在父组件传递undefined的时候不会被覆盖,但是小程序中被覆盖成null · Issue #1460 · dcloudio/uni-app · GitHub
Vue中父子组件生命周期执行顺序初探 - SegmentFault 思否
『 Vue小Case 』- Vue Prop中的 null vs undefined_mob604757008d56的技术博客_51CTO博客
vue父传子传值时子组件的props对应的值的default不能生效 - DAmarkday - 博客园 (cnblogs.com)