必须用工厂函数,因为Object和Array是引用类型,直接赋默认值会导致所有组件实例共享同一引用,引发状态污染;工厂函数确保每次返回全新副本。

Vue 组件中,为 Object 或 Array 类型的 prop 设置默认值时,必须使用工厂函数(即返回新对象/数组的函数),否则多个组件实例会共享同一引用,导致状态污染。
为什么必须用工厂函数?
JavaScript 中对象和数组是引用类型。如果直接写 default: { list: [] },这个对象在组件定义阶段就被创建一次,所有实例都指向它。一旦某个实例修改了 list.push() 或清空数组,其他实例也会同步“看到”变化——尤其在列表渲染、表单联动等场景下极易出错。
- 基础类型(
string、number、boolean)可直接赋值,默认值互不影响 - 引用类型(
Object、Array、Date、自定义类实例等)必须用工厂函数确保每次调用都生成全新副本 - Vue 在开发模式下会对未用工厂函数的对象/数组 default 值发出警告
正确写法示例
工厂函数要返回字面量或显式构造的新结构,避免复用外部变量:
-
✅ 推荐:直接字面量
user: { type: Object, default: () => ({ name: '', age: 0 }) } -
✅ 推荐:数组同理
items: { type: Array, default: () => [] } -
✅ 复杂结构可用解构
config: { type: Object, default: () => ({ ...baseConfig, theme: 'dark' }) } -
❌ 错误:复用外部对象
const DEFAULT = { a: 1 }; props: { data: { default: () => DEFAULT } }—— 所有实例仍共享引用
在 <script setup> 中的写法差异
使用 defineProps 时,工厂函数写法一致,但默认值需配合对象语法或 withDefaults:
立即学习“前端免费学习笔记(深入)”;
-
对象语法(运行时校验)
defineProps({ user: { type: Object, default: () => ({}) } }) -
withDefaults(推荐搭配 TypeScript)
const props = withDefaults(defineProps<{ user: object }>(), { user: () => ({}) }) -
⚠️ 注意:不能对解构后的 prop 直接设默认值,如
const { user = {} } = defineProps(...)是无效的,不触发响应式初始化
进阶提示:避免 setup 内二次污染
即使 props 默认值用了工厂函数,在 setup 中也不该直接用它创建响应式状态:
-
❌ 危险:
const state = reactive(props.user)—— 仍可能间接共享引用 -
✅ 安全:
const state = reactive({ ...props.user })或ref({ ...props.user }) - 需要深度响应且结构复杂时,优先用
toRefs或computed包装原始 props 字段,而非直接修改


















