props传递异步数据报错的问题

今天在改微信小程序的时候遇见一个比较有趣的问题。先上简版代码如下:

子组件用到了父组件传递过来的一个对象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) 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值