Skip to content
Search

Vue:Props

lastmod 2021-08-12created 2020-10-1510 edits

The props property of Vue:Component.

Passing data with Props

Every component instance has its own isolated scope. This means you cannot (and should not) directly reference parent data in a child component's template. Data can be passed down to child components using the props option.

A prop is a custom attribute for passing information from parent components. A child component needs to explicitly declare the props it expects to receive using the props option.

// 하위 컴포넌트의 JavaScript 파일
Vue.component('child', {
  // props 정의
  props: ['message'],
  // 데이터와 마찬가지로 prop은 템플릿 내부에서 사용할 수 있으며
  // vm의 this.message로 사용할 수 있습니다.
  template: '<span>{{ message }}</span>'
})

Then you can pass a plain string to it like so.

<!-- 상위 컴포넌트 html template -->
<child message="안녕하세요!"></child>

WARNING

props must be defined in the child component.

camelCase vs kebab-case

HTML attributes are case-insensitive, so when using non-string templates, camelCased prop names need to use their kebab-case (hyphen-delimited) equivalents.

Vue.component('child', {
  // JavaScript는 camelCase
  props: ['myMessage'],
  template: '<span>{{ myMessage }}</span>'
})
<!-- HTML는 kebab-case -->
<child my-message="안녕하세요!"></child>

This limitation does not apply when using string templates.

Dynamic Props

Similar to binding a normal attribute to an expression, you can use v-bind to dynamically bind props to data on the parent. Whenever the data is updated in the parent, it will also flow down to the child.

<div>
  <input v-model="parentMsg">
  <br>
  <child v-bind:my-message="parentMsg"></child>
</div>

It is simpler to use the shorthand syntax for v-bind.

<child :my-message="parentMsg"></child>

To pass all the properties of an object as props, you can use v-bind without an argument (v-bind instead of v-bind:prop-name). For example, given a todo object,

todo: {
  text: 'Learn Vue',
  isComplete: false
}

Then,

<todo-item v-bind="todo"></todo-item>

This behaves as follows:

<todo-item
  v-bind:text="todo.text"
  v-bind:is-complete="todo.isComplete"
></todo-item>

Literal vs. Dynamic

A common mistake beginners make is trying to pass a number using the literal syntax.

<!-- 이것은 일반 문자열 "1"을 전달합니다. -->
<comp some-prop="1"></comp>

However, because this is a literal prop, its value is passed as the plain string "1" instead of an actual number. To pass an actual JavaScript number, you need to use v-bind so that its value is evaluated as a JavaScript expression.

<!-- 이것은 실제 숫자로 전달합니다. -->
<comp v-bind:some-prop="1"></comp>

One-way data flow

All props form a one-way-down binding between the child property and the parent one. When the parent property updates, it flows down to the child, but not the other way around. This prevents child components from accidentally mutating the parent's state, which can make your app's data flow harder to reason about.

There are usually two cases where it's tempting to mutate a prop.

  • The prop is used only to pass in an initial value; the child component simply uses it as a local data property afterwards.
  • The prop is passed in as a raw value that needs to be transformed.

The proper answers to these use cases are:

  • Define a local data property that uses the prop's initial value as its initial value.

props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}

</syntaxhighlight>

  • Define a computed property computed from the prop's value.

props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}

</syntaxhighlight>

WARNING

Objects and arrays in JavaScript are passed by reference, so if the prop is an array or object, mutating the object or array itself in the child will affect the parent state.

Troubleshooting

Props with type Object/Array must use a factory function to return the default value

If the type of props is Object or Array, the default entry must be returned from a function.

props: {
    exampleDefaultObject: {
        type: Object,
        default() {
            return {}
        }
    },
    exampleDefaultArray: {
        type: Array,
        default() {
            return []
        }
    }
},

or in ES6:

props: {
    exampleDefaultObject: {
        type: Object,
        default: () => ({})
    },
    exampleDefaultArray: {
        type: Array,
        default: () => []
    }
},

If you use vue-property-decorator, use it as follows.

@Prop({ type: Array, default: () => [] })
readonly items!: Array<object>;

See also

Favorite site

author Zer0 sitemap