Vue3 Composition API+TS嵌套对象Props默认值未按预期生效
问题根本原因
Vue对prop默认值的处理是浅层级的全量替换逻辑,不会做深度属性合并,规则非常明确:
- 只有当父组件完全不传递对应prop时,才会执行default工厂函数返回预设的默认值
- 只要父组件传了该prop(哪怕传的对象只包含部分属性、缺了很多嵌套字段),Vue会直接使用传入的整个对象作为prop值,完全不会拿default里的对象和传入对象做任何层级的属性补全合并。
你当前的用例里父组件传了:dataset="{rooms: 5}",已经给dataset传了有效值,Vue就直接使用这个传入对象,不会补上default里预设的kitchen字段,所以控制台输出只有{rooms:5}。只有你完全省略:dataset传参时,才会触发default返回完整的默认对象,和你观察到的现象完全吻合。
代码实现的错误
你对Vue Object类型prop的默认值生效逻辑存在误解,写的default函数只覆盖了「dataset prop完全缺失」的场景,没有处理「dataset传了但内部属性/嵌套属性缺失」的补全场景,误以为Vue会自动递归合并嵌套对象的默认值,实际上Vue原生没有这个能力。
修复方法
根据你的嵌套层级选实现方式即可,两层结构直接手动合并最稳妥,避免引入额外的深合并依赖:
方式1:通过computed生成合并后的完整值(推荐,响应式稳定)
把默认值抽成独立常量,在组件内通过计算属性把传入值和默认值做合并,所有用到dataset的地方用这个计算属性即可:
<script setup lang="ts"> import { defineProps, PropType, computed } from 'vue'; export type KitchenType = { windows: number; }; export type DefaultTestType = { kitchen?: KitchenType; rooms?: number; }; // 抽离默认值 const getDefaultDataset = (): DefaultTestType => ({ kitchen: { windows: 5, }, rooms: 3, }) const props = defineProps({ dataset: { type: Object as PropType<DefaultTestType>, default: getDefaultDataset }, }); // 手动合并默认值和传入值 const mergedDataset = computed(() => { const defaultVal = getDefaultDataset() return { ...defaultVal, ...props.dataset, kitchen: { ...defaultVal.kitchen, ...props.dataset?.kitchen } } }) console.log('IAM DATASET: ', mergedDataset.value); </script>
方式2:在default函数内做合并(不需要额外计算属性)
default函数可以接收到父组件传入的原始prop值作为参数,直接在default内部完成合并返回即可,注意不要直接修改原始传入对象:
const props = defineProps({ dataset: { type: Object as PropType<DefaultTestType>, default: (rawVal?: DefaultTestType): DefaultTestType => { const base = { kitchen: { windows:5 }, rooms:3 } if (!rawVal) return base return { ...base, ...rawVal, kitchen: { ...base.kitchen, ...rawVal.kitchen } } } } })
如果你的数据嵌套层级超过3层,可以自己实现一个简单的深度合并函数替换上面的手动展开逻辑,Vue 3.3+版本也可以直接使用内置的mergeDeep工具函数完成深合并。
内容的提问来源于stack exchange,提问作者ii iml0sto1
相关产品推荐
相关产品推荐

