一、Props 声明
- 一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute
- 在使用
<script setup>
的单文件组件中,props 可以使用 defineProps() 宏来声明:
- 在没有使用
<script setup>
的组件中,prop 可以使用 props 选项来声明:
- 注意传递给
defineProps()
的参数和提供给props
选项的值是相同的,两种声明方式背后其实使用的都是prop
选项。 - 除了使用字符串数组来声明 prop 外,还可以使用对象的形式:
- 对于以对象形式声明中的每个属性,key 是 prop 的名称,而值则是该 prop 预期类型的构造函数。
- 对象形式的 props 声明不仅可以一定程度上作为组件的文档,而且如果其他开发者在使用你的组件时传递了错误的类型,也会在浏览器控制台中抛出警告。
- 如果你正在搭配 TypeScript 使用
<script setup>
,也可以使用类型标注来声明 props:
二、传递 prop 的细节
1、Prop 名字格式
- 如果一个 prop 的名字很长,应使用
camelCase 形式
,因为它们是合法的 JavaScript 标识符,可以直接在模板的表达式中使用,也可以避免在作为属性 key 名时必须加上引号。
- 虽然理论上你也可以在向子组件传递 props 时使用
camelCase 形式
(使用 DOM 模板时例外),但实际上为了和HTML attribute
对齐,我们通常会将其写为kebab-case 形式
:
- 对于组件名我们推荐使用
PascalCase
,因为这提高了模板的可读性,能帮助我们区分 Vue 组件和原生 HTML 元素。 - 然而对于传递
props
来说,使用 camelCase 并没有太多优势,因此我们推荐更贴近HTML 的书写风格
。
2、静态 vs. 动态 Prop
- 静态值形式的 props:
- 相应地,还有使用
v-bind
或缩写 : 来进行动态绑定的props
:
3、传递不同的值类型
- 任何类型的值都可以作为 props 的值被传递。
4、使用一个对象绑定多个 prop
- 如果你想要将一个对象的所有属性都当作 props 传入,你可以使用没有参数的
v-bind
,即只使用v-bind
而非:prop-name
。
- 以及下面的模板:
- 而这实际上等价于:
三、单向数据流
- 所有的
props
都遵循着单向绑定原则
,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。 - 这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。
- 另外,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。
- 若你这么做了,Vue 会在控制台上向你抛出警告:
1、导致你想要更改一个 prop 的需求通常来源于以下两种场景:
- prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是新定义一个局部数据属性,从 props 上获取初始值即可:
- 需要对传入的 prop 值做进一步的转换。在这种情况中,最好是基于该 prop 值定义一个计算属性:
2、更改对象 / 数组类型的 props(尽可能避免这样的更改)
- 当对象或数组作为 props 被传入时,虽然子组件无法更改 props 绑定,但仍然可以更改对象或数组内部的值。
- 这是因为 JavaScript 的对象和数组是按引用传递,而对 Vue 来说,禁止这样的改动虽然可能,但有很大的性能损耗,比较得不偿失。
- 这种更改的主要缺陷是它允许了子组件以某种不明显的方式影响父组件的状态,可能会使数据流在将来变得更难以理解。
- 在最佳实践中,你应该尽可能避免这样的更改,除非父子组件在设计上本来就需要紧密耦合。
- 在大多数场景下,子组件应该抛出一个事件来通知父组件做出改变。
四、Prop 校验
- Vue 组件可以更细致地声明对传入的 props 的校验要求。
- 比如我们上面已经看到过的类型声明,如果传入的值不满足类型要求,Vue 会在浏览器控制台中抛出警告来提醒使用者。
- 要声明对 props 的校验,你可以向 defineProps() 宏提供一个带有 props 校验选项的对象,例如:
一些补充细节
- 所有 prop 默认都是可选的,除非声明了
required: true
。 - 除
Boolean
外的未传递的可选 prop 将会有一个默认值undefined
。 - Boolean 类型的未传递 prop 将被转换为
false
。这可以通过为它设置 default 来更改——例如:设置为 default: undefined 将与非布尔类型的 prop 的行为保持一致。 - 如果声明了 default 值,那么在 prop 的值被解析为 undefined 时,无论 prop 是未被传递还是显式指明的 undefined,都会改为 default 值。
- 当 prop 的校验失败后,Vue 会抛出一个控制台警告 (在开发模式下)。