Prop基础用法

Prop 的大小写

在 HTML 标签中的属性名是大小写不敏感的,浏览器会自动把大写字符解释为小写字符。所以如果你在组件的 prop 中使用的是驼峰命名规则

Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})

那么在 HTML 中的属性应该这么写:

<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

如果你写成 <blog-post postTitle="hello!"></blog-post>这样是不对的,因为浏览器会自动给你转换成 <blog-post posttitle="hello!"></blog-post>

Prop 类型

prop 可以以字符串数组形式列出:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

如果你希望每个 prop 都有指定的类型,你可以以对象的形式列出 prop,对象的属性名和属性值分别就是 prop 的名称和类型。

props: {
	title: String,
	likes: Number,
	isPublished: Boolean,
	commentIds: Array,
	author: Object,
	callback: Function,
	contactsPromise: Promise
}

这不仅给你的组件提供了文档,还会在传入错误类型时从浏览器的控制台提示用户。

传递静态或动态 Prop

你可以像这样传入一个静态的值:

<blog-post title="My journey with Vue"></blog-post>

当然,还能够通过 v-bind 动态赋值:

<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post>
<!-- 简写 -->
<blog-post :title="post.title"></blog-post>

<!-- 动态赋予一个复杂表达式的值 -->
<blog-post :title="post.title + ' by ' + post.author.name"></blog-post>

这两个例子传入的都是字符串类型,但 prop 可以传入任意类型的值。

传入一个数字
<!-- 即便 42 是静态的,我们仍然需要 v-bind 来告诉 Vue,这是一个 JavaScript 表达式而不是一个字符串。 -->
<blog-post v-bind:likes="42"></blog-post>

<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:likes="post.likes"></blog-post>
传入一个布尔值
<!-- 包含该 prop 没有值的情况在内,都意味着 `true`。-->
<blog-post is-published></blog-post>

<!-- 即便 false 是静态的,我们仍然需要 v-bind 来告诉 Vue,这是一个 JavaScript 表达式而不是一个字符串。 -->
<blog-post v-bind:is-published="false"></blog-post>

<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:is-published="post.isPublished"></blog-post>
传入一个数组
<!-- 即便数组是静态的,我们仍然需要 `v-bind` 来告诉 Vue,这是一个 JavaScript 表达式而不是一个字符串。 -->
<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>

<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:comment-ids="post.commentIds"></blog-post>
传入一个对象
<!-- 即便数组是静态的,我们仍然需要 `v-bind` 来告诉 Vue,这是一个 JavaScript 表达式而不是一个字符串。 -->
<blog-post
  v-bind:author="{
    name: 'Veronica',
    company: 'Veridian Dynamics'
  }"
></blog-post>

<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:author="post.author"></blog-post>
传入一个对象的所有 property

如果你想要将一个对象的所有 property 都作为 prop 传入,你可以使用不带参数的 v-bind (取代 v-bind:prop-name)。例如,对于一个给定的对象 post

post: {
  id: 1,
  title: 'My Journey with Vue'
}

下面的模板:

<blog-post v-bind="post"></blog-post>

等价于:

<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>

单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父组件传递给子组件的值更新了,会向下流到子组件,但是子组件接收到父组件传递过来的值更新了,不会向上流到父组件。

你不应该在子组件内部更新 prop,这样做的话,Vue 会在控制台发出警告。如果你想要去变更 prop 的值,可以使用这两种方法:

  1. 子组件把接收到的 prop 数据存放到本地的 data 中,然后再去改变 data 中的数据
props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}
  1. 使用计算属性
props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。