一、props 的作用与设计目标
props 是父组件向子组件传递数据的唯一官方通道,其核心设计原则是:
-
单向数据流:父 → 子
-
子组件不得直接修改 props
-
props 主要用于数据展示和配置,而非业务状态管理
典型使用场景:
-
表单组件接收初始值
-
列表组件接收数据源
-
通用组件接收配置项(如 size、type、disabled)
二、props 的两种定义方式(Vue 3)
1️⃣ 数组形式(不推荐在生产中使用)
javascript
export default {
props: ['title', 'count']
}
特点:
-
无类型校验
-
无默认值
-
仅适合 demo 或极简组件
2️⃣ 对象形式(推荐)
javascript
export default {
props: {
title: String,
count: Number
}
}
这是最常用、最安全的方式。
三、完整 props 定义(工程级写法)
javascript
export default {
props: {
title: {
type: String,
required: true
},
count: {
type: Number,
default: 0
},
list: {
type: Array,
default: () => []
},
user: {
type: Object,
default: () => ({})
},
status: {
type: String,
validator(value) {
return ['success', 'error', 'warning'].includes(value)
}
}
}
}
关键字段说明
| 字段 | 说明 |
|---|---|
| type | 类型校验 |
| required | 是否必传 |
| default | 默认值 |
| validator | 自定义校验 |
四、支持的 type 类型
javascript
String
Number
Boolean
Array
Object
Date
Function
Symbol
多类型支持
javascript
props: { id: [String, Number] }
五、default 的正确写法(高频坑点)
❌ 错误写法(引用类型)
javascript
default: []
default: {}
✅ 正确写法
javascript
default: () => []
default: () => ({})
原因:
- 防止多个组件实例共享同一引用对象
六、父组件如何传递 props
1️⃣ 静态传值
javascript
<Child title="hello" />
2️⃣ 动态绑定(最常用)
javascript
<Child :count="num" />
3️⃣ 对象展开(批量传递)
html
<Child v-bind="userInfo" />
javascript
const userInfo = {
name: 'Tom',
age: 18
}
七、子组件中使用 props(Vue 3)
1️⃣ Options API
javascript
export default {
props: {
title: String
},
mounted() {
console.log(this.title)
}
}
2️⃣ Composition API(推荐)
javascript
<script setup>
const props = defineProps({
title: String,
count: Number
})
</script>
也可以解构(注意响应性):
javascript
const { title } = defineProps({
title: String
})
⚠ 解构后不是响应式(除非使用 toRefs)
javascript
import { toRefs } from 'vue'
const props = defineProps({ title: String })
const { title } = toRefs(props)
八、props 是只读的(非常重要)
❌ 错误:直接修改 props
javascript
props.count++
Vue 会警告:
Avoid mutating a prop directly
✅ 正确方式 1:使用本地状态
javascript
const localCount = ref(props.count)
✅ 正确方式 2:通过事件通知父组件
javascript
<Child :count="count" @update="count++" />
九、props 与 v-model(Vue 3 本质)
html
<Child v-model="value" />
等价于:
html
<Child :modelValue="value" @update:modelValue="($event)=>(value = $event)" />
子组件:
javascript
const props = defineProps({
modelValue: String
})
const emit = defineEmits(['update:modelValue'])
emit('update:modelValue', newValue)
十、props 的响应式特性
-
父组件数据变化 → 子组件 props 自动更新
-
props 本身是 浅只读响应式
-
引用类型内部属性可变,但不建议直接改
javascript
props.user.name = 'Jack' // 不推荐,破坏数据流
十一、props 常见错误总结
| 错误 | 说明 |
|---|---|
| 修改 props | 破坏单向数据流 |
| default 使用对象 | 引用共享 |
| 解构 props 丢响应式 | 需要 toRefs |
| props 承担业务状态 | 应使用 state / store |
| 传值与接收命名不一致 | kebab-case / camelCase |
十二、最佳实践建议(非常重要)
-
props 只负责展示和配置
-
复杂交互通过 emit / v-model
-
引用类型 default 必须是函数
-
对外组件必须写完整 props 校验
-
不要在子组件修改父状态
十三、与 Vue 2 的主要区别(简述)
| 项 | Vue 2 | Vue 3 |
|---|---|---|
| setup | ❌ | ✅ |
| defineProps | ❌ | ✅ |
| v-model | value + input | modelValue + update |
| TS 支持 | 一般 | 非常好 |