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 类型检查
类型 | 示例 | 类型检查方式 |
---|---|---|
String | String | typeof value === 'string' |
Number | Number | typeof value === 'number' |
Boolean | Boolean | typeof value === 'boolean' |
Array | Array | Array.isArray(value) |
Object | Object | typeof value === 'object' |
Date | Date | value instanceof Date |
Function | Function | typeof value === 'function' |
自定义类 | Person | value 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" />
十二、核心知识点
组件间通信机制
Props 是父组件向子组件传递数据的主要方式
遵循单向数据流原则,避免子组件修改父组件状态
响应式系统
Vue 的响应系统基于属性访问跟踪状态
在 3.5+ 版本中,解构的 props 仍保持响应性
类型校验机制
可通过多种方式声明 props 类型
支持运行时校验和 TypeScript 编译时校验
自定义校验函数可实现复杂校验逻辑