Vue3使用withDefaults和defineProps设置默认值的操作指南

 更新时间:2026年05月09日 09:09:43   作者:WebGirl  
文章详细比较了Vue3中使用defineProps和withDefaults设置props默认值的优缺点,defineProps简洁但代码臃肿,withDefaults分离定义与默认值设置,提高可读性,且默认值不会丢失,但代码分散,适用于复杂组件和动态生成默认值,促进代码复用和维护,需要的朋友可以参考下

直接在defineProps中设置默认值

优点:

  • 对于简单的组件,在defineProps对象中直接设置默认值是一种简洁的方式。所有props的定义,包括类型和默认值,都集中在一个地方,一目了然。可以很方便地看到每个props的类型和默认值信息。例如:
<script setup>
const props = defineProps({
    count: {type: Number,default: 0},
    name: {type: String,default: 'Guest'}
});
</script>
  • props是一个复杂的对象类型,并且默认值是一个对象时,直接在defineProps中设置默认值可以更好地利用对象的解构特性。例如:
<script setup>
const props = defineProps({
    user: {type: Object,default: () => ({name: 'Guest',age: 18})}
});
</script>

这里可以直接返回一个函数来生成默认的对象值,在组件初始化时会根据这个函数生成默认的user对象。

缺点:

  • props的定义比较复杂,或者需要对默认值进行一些复杂的计算或处理时,会使defineProps中的代码变得臃肿。例如,如果默认值需要调用一个函数来生成,会让props的定义看起来不够清晰。而且如果多个组件有相似的props默认值设置逻辑,这种方式不利于代码的复用。
  • Vue3 的defineProps解决了部分响应式问题(返回的是 “响应式 Proxy 对象”),但如果直接对defineProps的结果解构,依然会丢失默认值(响应式可通过toRefs保留,但默认值不行)
<!-- Vue3 组件:TestProps.vue(无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要解决的核心场景之一。

使用withDefaults设置默认值

优点:

  • withDefaults将默认值的设置与props的类型定义分离开来,使得代码结构更加清晰。特别是当props的类型定义比较复杂,或者有多个props需要设置默认值时,这种分离可以提高代码的可读性。例如:
<script setup>
import { withDefaults } from 'vue';
const props = defineProps({count: Number,name: String});
withDefaults(props, {count: 0,name: 'Guest'});
</script>
  • 先专注于props的类型定义,然后在另一个地方(withDefaults调用处)清晰地设置默认值。如果需要在多个组件中复用默认值设置逻辑,可以将withDefaults的调用封装成一个函数。
  • withDefaults在处理复杂对象类型的默认值时,与直接在defineProps中设置默认值的功能类似,但语法上略有不同。
 <script setup>
 import { withDefaults } from 'vue';
 const props = defineProps({user: Object});
 withDefaults(props, {user: () => ({name: 'Guest',age: 18})});
 </script>

同样是通过一个函数来生成默认的对象值,但需要注意的是,withDefaults在处理默认值时,对于引用类型(如对象、数组)的数据,如果默认值是一个引用类型的字面量(如{}[]),这个引用在所有组件实例中是共享的。这可能会导致一些意外的行为,例如一个组件修改了默认值对象的属性,可能会影响到其他组件的默认值。所以在使用withDefaults设置引用类型的默认值时,通常建议像上面那样返回一个新的对象或数组。

withDefaults解构后仍能读取到默认值

withDefaults是 Vue3 为defineProps设计的 “默认值增强工具”,它的核心作用有两个:

  1. defineProps的默认值与 TypeScript 类型紧密绑定(类型安全);
  2. 确保解构后仍能读取到默认值(彻底解决 Vue2 遗留的痛点)。
<!-- Vue3 组件:TestProps.vue(用withDefaults) -->
<template>
  <div>
    <!-- 父组件没传props时,正确显示默认值 -->
    <h1>{{ title }}</h1> <!-- "默认标题" -->
    <p>计数:{{ count }}</p> <!-- 100 -->
  </div>
</template>

<script setup lang="ts">
// 1. 用withDefaults定义props:默认值与类型绑定
const props = withDefaults(defineProps<{
  title?: string; // 可选类型,配合默认值
  count?: number; // 可选类型,配合默认值
}>(), {
  // 定义默认值(会自动校验类型,不符合TS类型会报错)
  title: "默认标题", 
  count: () => 100, // 复杂类型(如对象/数组)需用函数返回(避免复用问题)
});

// 2. 直接解构:默认值生效,且响应式保留(因为withDefaults处理过)
const { title, count } = props; 
console.log(title); // "默认标题"(正确读取默认值)
console.log(count); // 100(正确读取默认值)

// 3. 父组件传值时,会覆盖默认值(符合预期)
// 若父组件调用:<TestProps title="新标题" count={200} />
// 此时解构后 title = "新标题",count = 200
</script>

withDefaults 为什么能解决问题?

withDefaults本质是对defineProps返回的 “响应式 props 对象” 做了一层 “增强代理”:

  • 当访问props.title时,若父组件没传值,代理会自动返回withDefaults中定义的默认值;
  • 即便解构(const { title } = props),拿到的依然是 “带默认值逻辑的响应式引用”(而非原始值),所以默认值不会丢失;
  • 同时,withDefaults会强制默认值的类型与defineProps的 TS 类型一致(比如给title123,TS 会直接报错),比 Vue2 的type校验更严格。

缺点:

  • 代码的位置相对分散,需要查看两个地方(definePropswithDefaults)才能完整地了解props的定义和默认值情况。对于简单的props设置,可能会觉得有些繁琐。

withDefaults的使用场景

提高代码可读性和组织性

(1)复杂组件的**props**默认值设置

当组件具有多个props,并且每个props都需要设置默认值时,使用withDefaults可以让代码结构更清晰。

这样,props的类型定义和默认值设置分开,便于开发者阅读和理解。先看到props的类型定义,能快速了解组件接受哪些类型的属性,然后通过withDefaults看到默认值的设置,使得代码逻辑更加清晰,尤其在大型项目或者复杂组件开发中,有助于提高代码的可维护性。

(2)遵循组件开发规范和团队协作要求 在团队开发中,可能会有代码风格和组件开发规范的要求。使用withDefaults可以更好地符合这些规范。例如,规定props的类型定义和默认值设置分开,这样在代码审查或者新成员加入团队时,能够更容易理解组件的props逻辑。而且,这种规范的代码结构有助于提高代码的复用性,方便在其他组件中复用props的定义和默认值设置逻辑。

便于默认值的动态生成和复用

(1)动态生成默认值

有时候props的默认值需要根据一些外部条件或者组件内部状态来动态生成。使用withDefaults可以方便地实现这一点。例如,一个国际化组件,其默认文本需要根据当前语言环境来生成:

<script setup>
import { withDefaults, ref } from 'vue';
import i18n from './i18n';
const props = defineProps({
    buttonText: String
});
const currentLanguage = ref(i18n.getCurrentLanguage());
function generateDefaultButtonText() {
    return i18n.getTextForLanguage(currentLanguage.value, 'defaultButtonText');
}
withDefaults(props, {
    buttonText: generateDefaultButtonText
});
</script>

这里通过一个函数generateDefaultButtonText来动态生成buttonText的默认值,该函数可以根据当前语言环境获取合适的默认文本。这种方式使得默认值的生成更加灵活,能够适应不同的应用场景。

(2)默认值逻辑复用

如果多个组件需要相同或相似的默认值设置逻辑,可以将withDefaults的调用封装成一个函数。例如,有多个数据展示组件都需要对data属性设置默认值为空数组,对loading属性设置默认值为false

function setCommonDefaults(props) {
    withDefaults(props, {
        data: () => [],
        loading: false
    });
}

然后在各个组件中使用这个函数:

<script setup>
import { defineProps, withDefaults } from 'vue';
import { setCommonDefaults } from './commonDefaults';
const props = defineProps({
    data: Array,
    loading: Boolean
});
setCommonDefaults(props);
</script>

这样可以提高代码的复用性,减少重复代码,同时也便于统一修改默认值设置逻辑。

以上就是Vue3使用withDefaults和defineProps设置默认值的操作指南的详细内容,更多关于Vue3 withDefaults和defineProps设置默认值的资料请关注脚本之家其它相关文章!

相关文章

  • Vue 去除路径中的#号

    Vue 去除路径中的#号

    大家都知道vue-router有两种模式,hash模式和history模式,带#的则是hash模式。接下来给大家带来了Vue 去除路径中的#号的解决方法,感兴趣的朋友一起看看吧
    2018-04-04
  • Vue使用Echarts画柱状图详解

    Vue使用Echarts画柱状图详解

    数据的重要性我们大家都知道,就算再小的项目中都可能使用几个图表展示,我最近在做项目的过程中也是需要用到图表,最后选择了echarts图表库,这篇文章主要介绍了Vue使用Echarts画柱状图
    2022-12-12
  • Vue.js实现可编辑的表格

    Vue.js实现可编辑的表格

    这篇文章主要为大家详细介绍了Vue.js实现可编辑的表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • Template ref在Vue3中的实现原理详解

    Template ref在Vue3中的实现原理详解

    这篇文章主要为大家介绍了Template ref在Vue3中的实现原理示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 浅谈 vue 中的 watcher

    浅谈 vue 中的 watcher

    这篇文章主要介绍了vue 中的 watcher的相关资料,需要的朋友可以参考下
    2017-12-12
  • vue axios 二次封装的示例代码

    vue axios 二次封装的示例代码

    本篇文章主要介绍了vue axios 二次封装的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • vue中实现高德定位功能

    vue中实现高德定位功能

    这篇文章主要介绍了vue中实现高德定位功能,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • Vue.js学习笔记之常用模板语法详解

    Vue.js学习笔记之常用模板语法详解

    本篇文章主要介绍了Vue.js学习笔记之常用模板语法详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • 详解Vue中Computed与watch的用法与区别

    详解Vue中Computed与watch的用法与区别

    这篇文章主要介绍了Vue中computed和watch的使用与区别,文中通过示例为大家进行了详细讲解,对Vue感兴趣的同学,可以学习一下
    2022-04-04
  • VUEJS实战之构建基础并渲染出列表(1)

    VUEJS实战之构建基础并渲染出列表(1)

    这篇文章主要为大家详细介绍了VUEJS实战之构建基础并渲染出列表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-06-06

最新评论