Vue: 组件 Props

一、Props 声明方式

声明方式代码示例特点
数组形式defineProps(['foo'])简单易用,仅声明 prop 名
对象形式defineProps({ foo: String })可声明类型、默认值、是否必填等
TypeScript 类型标注defineProps<{ foo?: string }>()适用于 TypeScript 项目,类型安全

二、Props 类型声明

defineProps({
  propA: Number, // 基础类型
  propB: [String, Number], // 多种类型
  propC: { type: String, required: true }, // 必填项
  propD: { type: [String, null], required: true }, // 可为 null 的必填项
  propE: { type: Number, default: 100 }, // 带默认值
  propF: { type: Object, default: () => ({ message: 'hello' }) }, // 对象默认值
  propG: { validator: (value) => ['success', 'warning', 'danger'].includes(value) } // 自定义校验
})

三、响应式 Props 解构

1. 解构 Props
const { foo } = defineProps(['foo'])
2. 响应式特性
watchEffect(() => {
  console.log(foo) // 在 3.5+ 中,当 foo 变化时重新执行
})
3. 默认值解构
const { foo = 'hello' } = defineProps<{ foo?: string }>()

四、Prop 传递方式

传递方式示例说明
静态值<MyComponent title="Hello" />传递字符串常量
动态绑定<MyComponent :title="post.title" />传递变量或表达式
对象绑定<MyComponent v-bind="post" />一次性传递对象所有属性

五、Prop 类型传递示例

类型静态示例动态示例
Number<BlogPost :likes="42" /><BlogPost :likes="post.likes" />
Boolean<BlogPost is-published /><BlogPost :is-published="post.isPublished" />
Array<BlogPost :comment-ids="[234, 266, 273]" /><BlogPost :comment-ids="post.commentIds" />
Object<BlogPost :author="{ name: 'Veronica' }" /><BlogPost :author="post.author" />

六、Prop 校验规则

defineProps({
  propA: Number,
  propB: [String, Number],
  propC: { type: String, required: true },
  propD: { type: [String, null], required: true },
  propE: { type: Number, default: 100 },
  propF: { type: Object, default: () => ({ message: 'hello' }) },
  propG: { validator: (value) => ['success', 'warning', 'danger'].includes(value) }
})

七、Prop 类型检查

类型示例类型检查方式
StringStringtypeof value === 'string'
NumberNumbertypeof value === 'number'
BooleanBooleantypeof value === 'boolean'
ArrayArrayArray.isArray(value)
ObjectObjecttypeof value === 'object'
DateDatevalue instanceof Date
FunctionFunctiontypeof value === 'function'
自定义类Personvalue instanceof Person

八、Boolean 类型转换规则

声明类型示例转换结果
[Boolean, Number]<MyComponent disabled />true
[Boolean, String]<MyComponent disabled />true
[Number, Boolean]<MyComponent disabled />true
[String, Boolean]<MyComponent disabled />""

九、单向数据流原则

所有 props 都遵循单向绑定原则:props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。

不正确的做法:
props.foo = 'bar' // ❌ 警告!prop 是只读的!
正确做法:
// 1. 局部数据属性
const counter = ref(props.initialCounter)

// 2. 计算属性
const normalizedSize = computed(() => props.size.trim().toLowerCase())

十、响应式传递解构的 Props

const { foo } = defineProps(['foo'])

// 错误用法
watch(foo, /* ... */) // ❌ 传递的是一个值而不是响应式数据源

// 正确用法
watch(() => foo, /* ... */) // ✅ 通过 getter 包装
useComposable(() => foo) // ✅ 推荐做法

十一、总结图表

1. Props 声明方式对比图
┌──────────────┬───────────────┬────────────────────┐
│   声明方式   │  适用场景     │   优点              │
├──────────────┼───────────────┼────────────────────┤
│ 数组形式     │ 简单声明      │ 简洁易用           │
│ 对象形式     │ 完整声明      │ 支持类型、默认值等 │
│ TS 类型标注  │ TS 项目       │ 类型安全           │
└──────────────┴───────────────┴────────────────────┘
2. Prop 类型检查机制
┌───────────────┐
│    类型声明   │
├───────────────┤
│  基础类型检查 │
│  多类型支持   │
│  默认值       │
│  自定义校验   │
└───────────────┘
       ↓
┌──────────────────┐
│    运行时校验    │
├──────────────────┤
│  typeof 检查     │
│  instanceof 检查 │
│  自定义 validator│
└──────────────────┘
       ↓
┌────────────────────┐
│    开发环境警告    │
└────────────────────┘
3. Prop 传递方式流程图
Prop 传递方式
     │
     ├─ 静态值传递
     │   └─ <MyComponent title="Hello" />
     │
     ├─ 动态绑定
     │   └─ <MyComponent :title="post.title" />
     │
     └─ 对象绑定
         └─ <MyComponent v-bind="post" />

十二、核心知识点

  1. 组件间通信机制

    • Props 是父组件向子组件传递数据的主要方式

    • 遵循单向数据流原则,避免子组件修改父组件状态

  2. 响应式系统

    • Vue 的响应系统基于属性访问跟踪状态

    • 在 3.5+ 版本中,解构的 props 仍保持响应性

  3. 类型校验机制

    • 可通过多种方式声明 props 类型

    • 支持运行时校验和 TypeScript 编译时校验

    • 自定义校验函数可实现复杂校验逻辑

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小风华~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值