1. Props声明
- 一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute
在使用 <script setup> 的单文件组件中,props 可以使用 defineProps() 宏来声明:
<script setup>
const props = defineProps(['foo'])
console.log(props.foo)
</script>
除了使用字符串数组来声明 props 外,还可以使用对象的形式:
// 使用 <script setup>
defineProps({
title: String,
likes: Number
})
对于以对象形式声明的每个属性,key 是 prop 的名称,而值则是该 prop 预期类型的构造函数。比如,如果要求一个 prop 的值是 number 类型,则可使用 Number 构造函数作为其声明的值。
2. 响应式Props解构(vue3.5)
2.1. Vue3.5 之前
在 Vue 3.4 及之前版本,直接解构 defineProps() 会丢失响应性:
<script setup>
// ❌ 错误方式 - 会丢失响应性
const { title } = defineProps(['title'])
// 当父组件更新 title 时,这里的 title 不会更新
</script>
传统解决方案:需要使用 toRefs() 或 toRef() 来保持响应性:
<script setup>
import { toRefs, toRef } from 'vue'
const props = defineProps(['title', 'count'])
// 方案1:toRefs 保持响应式引用
const { title, count } = toRefs(props)
// 方案2:toRef 单个转换
const title = toRef(props, 'title')
</script>
2.2. Vue3.5 新特征
Vue 3.5 允许直接解构 defineProps(),同时自动保持响应性:
<script setup>
// ✅ Vue 3.5+ 可以直接解构,保持响应性
const { title, count } = defineProps(['title', 'count'])
// 这些变量是响应式的,会随父组件更新而更新
</script>
3. 传递prop的细节
3.1. Prop名字格式
如果一个 prop 的名字很长,应使用 camelCase 形式,因为它们是合法的 JavaScript 标识符,可以直接在模板的表达式中使用,也可以避免在作为属性 key 名时必须加上引号。
defineProps({
greetingMessage: String
})
<span>{{ greetingMessage }}</span>
3.2. props校验详解
3.2.1. 基础语法(对象语法)
<script setup>
const props = defineProps({
name: {
type: String,
required: true,
default: '匿名用户',
validator: (value) => {
return value.length > 0
}
}
})
</script>
也可以支持多类型,如下
<script setup>
const props = defineProps({
// 可以是字符串或数字
id: [String, Number],
// 可以是字符串或布尔值
flag: [String, Boolean],
// 多种类型
value: [String, Number, Boolean, Object]
})
</script>