第3章:组件化开发基础
第7节:Props组件通信
3.7.1 Props声明与类型检查
Props是Vue.js中父组件向子组件传递数据的主要方式。在子组件中,我们可以通过props选项声明接收哪些属性,并可以指定类型、默认值、是否必填等验证规则。
基本Props声明
export default {
props: {
// 基础类型检查
title: String,
// 多个可能的类型
likes: [String, Number],
// 必填且为数字
age: {
type: Number,
required: true
},
// 带默认值的对象
config: {
type: Object,
default: () => ({ show: true })
}
}
}Props类型
Vue支持以下Props类型:
StringNumberBooleanArrayObjectDateFunctionSymbol- 自定义构造函数
自定义类型检查
// 自定义构造函数
function Person(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
export default {
props: {
author: {
type: Person,
validator: (value) => {
// 自定义验证函数
return typeof value.firstName === 'string' && typeof value.lastName === 'string'
}
}
}
}在组合式API中使用Props
<script setup>
// 基础声明
const props = defineProps(['title', 'likes'])
// 带类型检查的声明
const props = defineProps({
title: String,
likes: Number
})
// 使用TypeScript类型
interface Props {
title: string
likes?: number
}
const props = defineProps<Props>()
</script>3.7.2 单向数据流原则
Vue.js遵循单向数据流原则:
- 父组件可以向子组件传递数据(通过Props)
- 子组件不能直接修改父组件传递的数据
- 子组件如果需要修改数据,应该通过事件通知父组件,由父组件进行修改
为什么不能直接修改Props?
- 可维护性:数据流清晰,容易追踪数据变化
- 可预测性:父组件可以完全控制传递给子组件的数据
- 避免冲突:防止多个子组件同时修改同一数据导致的冲突
子组件如何响应Props变化?
如果子组件需要根据Props变化执行某些逻辑,可以使用watch或computed:
export default {
props: ['count'],
computed: {
// 基于Props计算新值
doubleCount() {
return this.count * 2
}
},
watch: {
// 监听Props变化
count(newVal, oldVal) {
console.log(`count changed from ${oldVal} to ${newVal}`)
}
}
}在组合式API中:
<script setup>
import { computed, watch } from 'vue'
const props = defineProps(['count'])
const doubleCount = computed(() => props.count * 2)
watch(() => props.count, (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`)
})
</script>3.7.3 Prop的大小写命名
在Vue中,Prop的命名需要注意HTML属性和JavaScript属性的差异:
HTML中的kebab-case
在HTML模板中,建议使用kebab-case(短横线分隔)命名:
<my-component post-title="Hello"></my-component>JavaScript中的camelCase
在JavaScript中,建议使用camelCase(驼峰式)命名:
export default {
props: ['postTitle'],
mounted() {
console.log(this.postTitle) // Hello
}
}Vue会自动将kebab-case转换为camelCase,所以以下两种写法是等价的:
<!-- HTML中使用kebab-case -->
<my-component post-title="Hello"></my-component>
<!-- JavaScript中使用camelCase -->
export default {
props: ['postTitle']
}在组件模板中使用
在组件的模板中,可以直接使用camelCase或kebab-case访问Props:
<template>
<div>
<h1>{{ postTitle }}</h1> <!-- 推荐 -->
<h1>{{ post-title }}</h1> <!-- 也可以,但不推荐 -->
</div>
</template>Props使用最佳实践
- 使用明确的类型检查:为Props添加类型检查,提高代码质量
- 设置合理的默认值:为可选Props设置默认值,避免undefined错误
- 遵循单向数据流:不要直接修改Props,通过事件通知父组件
- 使用computed处理Props:对于需要转换的Props,使用computed属性
- 合理命名:使用语义化的名称,遵循大小写规范
总结
Props是Vue组件间通信的基础,通过掌握Props的声明、类型检查、单向数据流原则和命名规范,你可以编写出健壮、可维护的组件。记住,Props是只读的,子组件永远不应该直接修改父组件传递的数据。
在下一节中,我们将学习组件间通信的另一种方式:自定义事件。