引言
组件在被创建时所需要从外部获取的初始状态值,可以通过Vue Props来声明。显示声明所需要,同时"放过"透传的 attribute(见后一篇)
一,声明Props
1. 简单数组声明
1)SFC中的 <script setup>内,利用defineProps()宏来声明
<script setup>
const props = defineProps(['foo'])
console.log(props.foo)
</script>
2)export + setup()内通过props选项声明
export default {
props: ['foo'],
setup(props) {
// setup() 接收 props 作为第一个参数
console.log(props.foo)
}
}
2. 详细对象声明
defineProps({
// 基础类型检查
// (给出 `null` 和 `undefined` 值则会跳过任何类型检查)
propA: Number,
// 多种可能的类型
propB: [String, Number],
// 必传,且为 String 类型
propC: {
type: String,
required: true
},
// Number 类型的默认值
propD: {
type: Number,
default: 100
},
// 对象类型的默认值
propE: {
type: Object,
// 对象或数组的默认值
// 必须从一个工厂函数返回。
// 该函数接收组件所接收到的原始 prop 作为参数。
default(rawProps) {
return { message: 'hello' }
}
},
// 自定义类型校验函数
// 在 3.4+ 中完整的 props 作为第二个参数传入
propF: {
validator(value, props) {
// The value must match one of these strings
return ['success', 'warning', 'danger'].includes(value)
}
},
// 函数类型的默认值
propG: {
type: Function,
// 不像对象或数组的默认,这不是一个
// 工厂函数。这会是一个用来作为默认值的函数
default() {
return 'Default function'
}
}
})
3. 若使用TypeScript特性,可用 类型标注 类声明
<script setup lang="ts">
defineProps<{
title?: string
likes?: number
}>()
</script>
二、传递Props
1. 名称格式的理论是实践
1)使用camelCase 格式声明
defineProps({
greetingMessage: String
})
2)使用kebab-case格式传递值(同时支持DOM内模板)
<MyComponent greeting-message="hello" />
3)组件名推荐使用 PascalCase,因为这提高了模板的可读性,能帮助我们区分 Vue 组件和原生 HTML 元素。
2. 静态OR动态传值
1).静态传值
<BlogPost title="My journey with Vue" />
2).动态绑定传值
// String类型值
<!-- 根据一个变量的值动态传入 -->
<BlogPost :title="post.title" />
<!-- 根据一个更复杂表达式的值动态传入 -->
<BlogPost :title="post.title + ' by ' + post.author.name" />
// Number类型值
<!-- 虽然 `42` 是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :likes="42" />
<!-- 根据一个变量的值动态传入 -->
<BlogPost :likes="post.likes" />
// Boolean
<!-- 仅写上 prop 但不传值,会隐式转换为 `true` -->
<BlogPost is-published />
<!-- 虽然 `false` 是静态的值,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :is-published="false" />
<!-- 根据一个变量的值动态传入 -->
<BlogPost :is-published="post.isPublished" />
// Array
<!-- 虽然这个数组是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :comment-ids="[234, 266, 273]" />
<!-- 根据一个变量的值动态传入 -->
<BlogPost :comment-ids="post.commentIds" />
// Object
<!-- 虽然这个对象字面量是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost
:author="{
name: 'Veronica',
company: 'Veridian Dynamics'
}"
/>
<!-- 根据一个变量的值动态传入 -->
<BlogPost :author="post.author" />
3. 声明多个Prop,由一个Object传给全部值
const post = {
id: 1,
title: 'My Journey with Vue'
}
<BlogPost v-bind="post" />
等价于
<BlogPost :id="post.id" :title="post.title" />
三、传值运行时行为
1. 运行时校验类型
String
Number
Boolean
Array
Object
Date
Function
Symbol
自定义类或构造函数
自定义类
// 类定义
class Person {
constructor(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
}
// 声明中使用自定义类
defineProps({
author: Person
})
2. 其他细节
1), prop默认可选, 除非指定必须required: true
2), 除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined
3), Boolean 类型的未传递 prop 将被转换为 false, 也可以通过设置default = undefined来和非Boolean类型prop的行为保持一致
4), 在 prop 的值被解析为 undefined 时,查看是否定义有default
5), 当 prop 的校验失败后,Vue 会抛出一个控制台警告 (在开发模式下)
6), 当Boolean类型prop允许多类型时, 有一种情况例外
// 传 disabled 将被解析为空字符串 (disabled="")
defineProps({
disabled: [String, Boolean]
})
一致行为的解析
// 传 disabled 将被转换为 true
defineProps({
disabled: [Boolean, Number]
})
// 传 disabled 将被转换为 true
defineProps({
disabled: [Boolean, String]
})
// 传 disabled 将被转换为 true
defineProps({
disabled: [Number, Boolean]
})