Props 声明
一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute
props 需要使用 props 选项来定义
| export default { |
| props: ['foo'], |
| created() { |
| |
| console.log(this.foo) |
| } |
| } |
| |
| 除了使用字符串数组来声明 prop 外,还可以使用对象的形式 |
| |
| export default { |
| props: { |
| title: String, |
| likes: Number |
| } |
| } |
| |
| 对于以对象形式声明中的每个属性,key 是 prop 的名称,而值则是该 prop 预期类型的构造函数。比如,如果要求一个 prop 的值是 number 类型,则可使用 Number 构造函数作为其声明的值 |
| |
| 对象形式的 props 声明不仅可以一定程度上作为组件的文档,而且如果其他开发者在使用你的组件时传递了错误的类型,也会在浏览器控制台中抛出警告 |
传递 prop 的细节
Prop 名字格式
如果一个 prop 的名字很长,应使用 camelCase 形式,因为它们是合法的 JavaScript 标识符,可以直接在模板的表达式中使用,也可以避免在作为属性 key 名时必须加上引号
| export default { |
| props: { |
| greetingMessage: String |
| } |
| } |
| |
| <span>{{ greetingMessage }}</span> |
虽然理论上你也可以在向子组件传递 props 时使用 camelCase 形式 (使用 DOM 模板时例外),但实际上为了和 HTML attribute 对齐,我们通常会将其写为 kebab-case 形式
| <MyComponent greeting-message="hello" /> |
| |
| 对于组件名我们推荐使用 PascalCase,因为这提高了模板的可读性,能帮助我们区分 Vue 组件和原生 HTML 元素。然而对于传递 props 来说,使用 camelCase 并没有太多优势,因此我们推荐更贴近 HTML 的书写风格 |
静态 vs. 动态 Prop
使用 v-bind 或缩写 : 来进行动态绑定的 props
| 静态值形式的 props |
| <BlogPost title="My journey with Vue" /> |
| |
| |
| <BlogPost :title="post.title" /> |
| |
| |
| <BlogPost :title="post.title + ' by ' + post.author.name" /> |
传递不同的值类型
任何类型的值都可以作为 props 的值被传递。
| 1、Number |
| |
| |
| |
| <BlogPost :likes="42" /> |
| |
| |
| <BlogPost :likes="post.likes" /> |
| 2、Boolean |
| |
| |
| <BlogPost is-published /> |
| |
| |
| |
| <BlogPost :is-published="false" /> |
| |
| |
| <BlogPost :is-published="post.isPublished" /> |
| 3、Array |
| |
| |
| |
| <BlogPost :comment-ids="[234, 266, 273]" /> |
| |
| |
| <BlogPost :comment-ids="post.commentIds" /> |
| 4、Object |
| |
| |
| |
| <BlogPost |
| :author="{ |
| name: 'Veronica', |
| company: 'Veridian Dynamics' |
| }" |
| /> |
| |
| |
| <BlogPost :author="post.author" /> |
使用一个对象绑定多个 prop
如果你想要将一个对象的所有属性都当作 props 传入,你可以使用没有参数的 v-bind,即只使用 v-bind 而非 :prop-name
| export default { |
| data() { |
| return { |
| post: { |
| id: 1, |
| title: 'My Journey with Vue' |
| } |
| } |
| } |
| } |
| |
| <BlogPost v-bind="post" /> 等价于 |
| |
| <BlogPost :id="post.id" :title="post.title" /> |
单向数据流
所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递
这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解
另外,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。若你这么做了,Vue 会在控制台上向你抛出警告
| export default { |
| props: ['foo'], |
| created() { |
| |
| this.foo = 'bar' |
| } |
| } |
导致你想要更改一个 prop 的需求通常来源于以下两种场景
| 1、prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是新定义一个局部数据属性,从 props 上获取初始值即可 |
| |
| export default { |
| props: ['initialCounter'], |
| data() { |
| return { |
| |
| |
| counter: this.initialCounter |
| } |
| } |
| } |
| |
| 2、需要对传入的 prop 值做进一步的转换。在这种情况中,最好是基于该 prop 值定义一个计算属性: |
| |
| export default { |
| props: ['size'], |
| computed: { |
| |
| normalizedSize() { |
| return this.size.trim().toLowerCase() |
| } |
| } |
| } |
更改对象 / 数组类型的 props
| 当对象或数组作为 props 被传入时,虽然子组件无法更改 props 绑定,但仍然可以更改对象或数组内部的值。这是因为 JavaScript 的对象和数组是按引用传递,而对 Vue 来说,禁止这样的改动虽然可能,但有很大的性能损耗,比较得不偿失 |
| |
| 这种更改的主要缺陷是它允许了子组件以某种不明显的方式影响父组件的状态,可能会使数据流在将来变得更难以理解。在最佳实践中,你应该尽可能避免这样的更改,除非父子组件在设计上本来就需要紧密耦合。在大多数场景下,子组件应该抛出一个事件来通知父组件做出改变 |
Prop 校验
Vue 组件可以更细致地声明对传入的 props 的校验要求。比如我们上面已经看到过的类型声明,如果传入的值不满足类型要求,Vue 会在浏览器控制台中抛出警告来提醒使用者。这在开发给其他开发者使用的组件时非常有用
要声明对 props 的校验,你可以向 props 选项提供一个带有 props 校验选项的对象
| export default { |
| props: { |
| |
| |
| propA: Number, |
| |
| propB: [String, Number], |
| |
| propC: { |
| type: String, |
| required: true |
| }, |
| |
| propD: { |
| type: Number, |
| default: 100 |
| }, |
| |
| propE: { |
| type: Object, |
| |
| |
| |
| default(rawProps) { |
| return { message: 'hello' } |
| } |
| }, |
| |
| propF: { |
| validator(value) { |
| |
| return ['success', 'warning', 'danger'].includes(value) |
| } |
| }, |
| |
| propG: { |
| type: Function, |
| |
| default() { |
| return 'Default function' |
| } |
| } |
| } |
| } |
| |
| 一些补充细节: |
| |
| 1、所有 prop 默认都是可选的,除非声明了 required: true。 |
| |
| 2、除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined。 |
| |
| 3、Boolean 类型的未传递 prop 将被转换为 false。这可以通过为它设置 default 来更改——例如:设置为 default: undefined 将与非布尔类型的 prop 的行为保持一致。 |
| |
| 4、如果声明了 default 值,那么在 prop 的值被解析为 undefined 时,无论 prop 是未被传递还是显式指明的 undefined,都会改为 default 值。 |
运行时类型检查
| 校验选项中的 type 可以是下列这些原生构造函数: |
| |
| String |
| Number |
| Boolean |
| Array |
| Object |
| Date |
| Function |
| Symbol |
| 另外,type 也可以是自定义的类或构造函数,Vue 将会通过 instanceof 来检查类型是否匹配。例如下面这个类 |
| |
| class Person { |
| constructor(firstName, lastName) { |
| this.firstName = firstName |
| this.lastName = lastName |
| } |
| } |
| |
| 你可以将其作为一个 prop 的类型 |
| |
| export default { |
| props: { |
| author: Person |
| } |
| } |
| |
| Vue 会通过 instanceof Person 来校验 author prop 的值是否是 Person 类的一个实例 |
Boolean 类型转换
为了更贴近原生 boolean attributes 的行为,声明为 Boolean 类型的 props 有特别的类型转换规则。以带有如下声明的 <MyComponent> 组件为例:
| export default { |
| props: { |
| disabled: Boolean |
| } |
| } |
| |
| |
| <MyComponent disabled /> |
| |
| |
| <MyComponent /> |
| |
| 当一个 prop 被声明为允许多种类型时,例如 |
| |
| export default { |
| props: { |
| disabled: [Boolean, Number] |
| } |
| } |
| |
| 无论声明类型的顺序如何,Boolean 类型的特殊转换规则都会被应用 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律