Prop


This page assumes that you have read Component Basics. If you don’t know much about components yet, I recommend you read it first.


Directory

  • The case of Prop

  • Prop Type

  • ## Pass static or dynamic Prop

    • Pass in a number

    • Pass in a Boolean value

    • Pass in an array

    • Pass in an object

    • Pass in all properties of an object

  • One-way data flow

  • Prop Verification

    • Type Check

  • Not Prop features

    • Replace/merge existing features

    • Disable feature inheritance



#Prop case (camelCase vs kebab-case)

Attribute names in HTML are case-insensitive, so the browser will interpret all uppercase characters as lowercase characters. This means that when you use a template in the DOM, the camelCase prop name needs to use its equivalent kebab-case (dash separated naming) name:
Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

Once again, if If you use string templates, this limitation does not exist.


Prop type

So far, we have only seen the string array form Listed props:

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

However, usually you want each prop to have a specified value type. At this point, you can list the props in object form. The names and values ​​of these properties are the respective names and types of the props:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // or any other constructor
}

This not only provides documentation for your components, but also provides documentation when they encounter The wrong type is prompted when the user is prompted from the browser's JavaScript console. You'll see

type checking and other prop validation

in the remainder of this page.

Pass static or dynamic Prop


Like this, you already know that you can pass a static value to prop like this:

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

You also know that prop can be dynamically assigned through v-bind, for example:

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

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

In the above two examples, the values ​​we pass in are all string types. , but in fact any type of value can be passed to a prop.


Pass in a number

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

<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:likes="post.likes"></blog-post>


Pass in a Boolean value

<!-- 包含该 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>


##Pass in an array

<!-- 即便数组是静态的,我们仍然需要 `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>


Pass in an object

<!-- 即便对象是静态的,我们仍然需要 `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>


## Pass in all the properties of an objectIf you want to pass in all the properties of an object as props, you can use

v-bind## without parameters # (replaces

v-bind:prop-name). For example, for a given object post:

post: {
  id: 1,
  title: 'My Journey with Vue'
}
the following template:
<blog-post v-bind="post"></blog-post>

is equivalent to:

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


One-way data flow

All props form a

One-way downward binding between their parent and child props
: Updates to parent props will flow downward to child components, but not vice versa. This will prevent the child component from accidentally changing the state of the parent component, making the data flow of your application difficult to understand.

In addition, every time the parent component is updated, all props in the child component will be refreshed to the latest values. This means that you should not

change props inside a child component. If you do this, Vue will issue a warning in the browser's console.

There are two common situations where you try to change a prop:

1.

This prop is used to pass an initial value; the subcomponent then wants to use it as a local prop data to use.

In this case, it is best to define a local data attribute and use this prop as its initial value:

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}
 2. This prop is passed in as a primitive value and Conversion is required.

In this case, it is best to use the value of this prop to define a computed property:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}
Note that in JavaScript objects and arrays are passed in by reference, so for an array Or object type prop, changing the object or array itself in the child component will

affect the state of the parent component.

Prop Validation


We can specify validation requirements for component props, such as the types you know. If a requirement is not met, Vue will warn you in the browser console. This is especially helpful when developing a component that will be used by others.

To customize how props are validated, you can provide an object with validation requirements for the value in props instead of a string array. For example:

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

When prop verification fails, Vue (development environment build version) will generate a console warning.

Note that those props will be verified before a component instance is created , so the properties of the instance (such as data, computed, etc. ) is not available in default or validator functions.

Type check

type can be in the following native constructor A:

  • String

  • ##Number

  • ##Boolean

  • Array

  • ##Object
  • Date
  • Function
  • Symbol
  • In addition,
  • type
can also be a custom constructor, and checked through

instanceof. For example, given the following ready-made constructor:

function Person (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}
you can use:
Vue.component('blog-post', {
  props: {
    author: Person
  }
})

to verify that the value of the

author

prop is passed

new Person Created.


Non-Prop attributes

A non-prop attribute is passed to a component , but the component does not have the characteristics defined by the corresponding prop.


Because explicitly defined props are suitable for passing information to a subcomponent, however, the author of the component library cannot always foresee what scenarios the component will be used for. This is why components can accept arbitrary attributes, and these attributes will be added to the root element of the component.

For example, imagine that you use a third-party

<bootstrap-date-input>

component through a Bootstrap plug-in that requires a third-party

<input> uses a data-date-picker feature. We can add this attribute to your component instance:

<bootstrap-date-input data-date-picker="activated"></bootstrap-date-input>
Then this data-date-picker="activated"

attribute will be automatically added to

<bootstrap- On the root element of date-input>.


Replace/merge existing features

Imagine<bootstrap-date -input>

The template is like this:

<input type="date" class="form-control">

In order to customize a theme for our date picker plugin, we may need to add a special class name like this:

<bootstrap-date-input
  data-date-picker="activated"
  class="date-picker-theme-dark"
></bootstrap-date-input>

In this case, we define two different ## The value of #class:

  • form-control, which is set in the template of the component

  • date-picker-theme-dark, which is passed in from the parent of the component

For most features, it is provided externally to The value of the component will replace the value set internally in the component. So if

type="text" is passed in, type="date" will be replaced and destroyed! Fortunately, the class and style attributes are a little smarter, i.e. the values ​​on both sides are combined to get the final value: form-control date-picker- theme-dark.


Disable attribute inheritance

If you

don't want the root element of the component To inherit attributes, you can set inheritAttrs: false in the component's options. For example:

Vue.component('my-component', {
  inheritAttrs: false,
  // ...
})

This is especially suitable for use with the instance's

$attrs attribute, which contains the attribute name and attribute value passed to a component, for example:

{
  required: true,
  placeholder: 'Enter your username'
}

has With

inheritAttrs: false and $attrs, you can manually decide which element these attributes will be assigned to. It is often used when writing basic components:

Vue.component('base-input', {
  inheritAttrs: false,
  props: ['label', 'value'],
  template: `
    <label>
      {{ label }}
      <input
        v-bind="$attrs"
        v-bind:value="value"
        v-on:input="$emit('input', $event.target.value)"
      >
    </label>
  `
})

Note:

inheritAttrs: false The option will not affect # Binding of ##style and class.

This mode allows you to use base components more like raw HTML elements without worrying about which element is the real root element:
<base-input
  v-model="username"
  required
  placeholder="Enter your username"
></base-input>