【Vue】defineProps直接和withDefaults设置默认值区别
分类: Vue 12 0
一、先回顾:Vue2 中 “解构丢失默认值” 的真实痛点(附案例)
在 Vue2 的 Options API 中,props 的默认值通过default
配置定义,但只要对this.$props
或this
进行解构,就会同时丢失响应式和默认值,这是 Vue2 响应式原理(基于 Object.defineProperty)的固有局限。
{{ title }}
计数:{{ count }}
为什么会这样?
-
Vue2 的`this`是 “响应式代理对象”,`this.title`本质是通过`this.$props.title`的 getter 访问,自带 “读取默认值” 的逻辑;
- 一旦解构(`const { title } = this`),拿到的是 “当前时刻的原始值”(若父组件没传 props,此时值为`undefined`),既失去了对`$props`的关联,也无法触发默认值的读取逻辑;
- 即便直接解构`this.$props`(`const { title } = this.$props`),结果也一样 —— 因为`$props`的响应式依赖 “访问行为”,解构会切断这种依赖。
Vue2 中要规避这个问题,只能不解构,全程用`this.title`访问,代码灵活性受限。
二、Vue3 不用 withDefaults:解构仍会丢默认值(附案例)
Vue3 的`defineProps`解决了部分响应式问题(返回的是 “响应式 Proxy 对象”),但如果直接对`defineProps`的结果解构,依然会丢失默认值(响应式可通过`toRefs`保留,但默认值不行)
Vue3 无 withDefaults 的案例:解构后默认值 “失效”
```
<template>
<div>
<!-- 父组件没传props时,期望显示默认值,实际显示 undefined -->
<h1>{{ title }}</h1>
<p>计数:{{ count }}</p>
</div>
</template>
<script setup lang="ts">
// 1. 定义props并设置默认值(通过第二个参数)
const props = defineProps<{
title?: string;
count?: number;
}>({
title: {
type: String,
default: "默认标题"
},
count: {
type: Number,
default: 100
}
});
// 2. 直接解构:丢失默认值(响应式可通过toRefs保留,但默认值不行)
const { title, count } = props;
console.log(title); // undefined(而非 "默认标题")
console.log(count); // undefined(而非 100)
// 3. 用toRefs解构:保留响应式,但仍丢失默认值
import { toRefs } from "vue";
const { title: refTitle, count: refCount } = toRefs(props);
console.log(refTitle.value); // undefined(依然没有默认值)
</script>
可见:Vue3 中即便用了defineProps
,若不配合withDefaults
,Vue2 的 “解构丢失默认值” 问题依然存在 —— 这正是withDefaults
要解决的核心场景之一。
## 三、Vue3 withDefaults:同时解决 “解构丢默认值” 和 “类型安全”(附案例)
withDefaults
是 Vue3 为defineProps
设计的 “默认值增强工具”,它的核心作用有两个:
1. 让defineProps
的默认值与 TypeScript 类型紧密绑定(类型安全);
1. 确保**解构后仍能读取到默认值**(彻底解决 Vue2 遗留的痛点)。
##### Vue3 withDefaults 案例:解构后默认值 “生效”
{{ title }}
计数:{{ count }}
##### withDefaults 为什么能解决问题?
withDefaults
本质是对defineProps
返回的 “响应式 props 对象” 做了一层 “增强代理”:
- 当访问props.title
时,若父组件没传值,代理会自动返回withDefaults
中定义的默认值;
- 即便解构(const { title } = props
),拿到的依然是 “带默认值逻辑的响应式引用”(而非原始值),所以默认值不会丢失;
- 同时,withDefaults
会强制默认值的类型与defineProps
的 TS 类型一致(比如给title
传123
,TS 会直接报错),比 Vue2 的type
校验更严格。
共 0 条评论关于 “【Vue】defineProps直接和withDefaults设置默认值区别”