Vue Components - Props

YEZI🎐·2022년 11월 24일
0

Vue

목록 보기
18/45

Props

컴포넌트 A와 컴포넌트 B가 있다고 가정할 때, 서로 의사 소통을 필요로 한다면
부모는 자식에게 데이터를 전달할 수 있어야 하고, 자식은 자신에게 일어난 일을 부모에게 알릴 수 있어야 한다.

Vue.js에서 부모-자식 컴포넌트 관계는
props는 아래로(부모에서 자식),events는 위로(자식에서 부모로) 라고 요약할 수 있다.
부모는 props를 통해 자식에게 데이터를 전달하고,
자식은 events를 통해 부모에게 메세지를 보낸다.

데이터 전달

모든 컴포넌트 인스턴스에는 자체 격리 된 범위가 있어 하위 컴포넌트의 템플릿에서 상위 데이터를 직접 참조할 수 없다.
부모 컴포넌트는 props 옵션을 사용하여 데이터를 하위 컴포넌트로 전달할 수 있다.
하위 컴포넌트는 props 옵션을 사용하여 수신할 것으로 기대되는 props를 명시적으로 선언해야 한다.

<!-- 부모 컴포넌트 -->
<!-- HTML 속성은 대소문자를 구분하지 않으므로 kebab-case 사용  -->
<child from-parent="hello!"></child>
// 자식 컴포넌트
Vue.component('child', {
  props: ['fromParent'],	// JavaScript에서는 camelCase 사용
  template: '<h3>{{ fromParent }}</h3>'
})
<!-- 결과 화면 -->
<h3>hello!</h3>

동적 props

정규 속성을 표현식에 바인딩 하는 것과 비슷하게,
v-bind를 사용하여 부모의 데이터에 props를 동적으로 바인딩할 수 있다.
데이터가 상위에서 업데이트 될 때마다 하위 데이터에게도 전달된다.

<!-- 부모 컴포넌트 -->
<div>
  <input v-model="inputMsg">
  <child v-bind:fromParent="inputMsg"></child>
</div>

객체의 모든 속성을 props로 전달하려면, 인자 없이 v-bind를 쓸 수 있다.
(v-bind:prop명 대신 v-bind)

// 부모 컴포넌트
parentObject: {
  test: 'Learn Vue',
  isComplete: false
}
<!-- 부모 컴포넌트 -->
<todo-item v-bind="parentObject"></todo-item>
<!-- ↑ 같은 거 ↓ -->
<todo-item
  v-bind:text="parentObject.text"
  v-bind:is-complete="parentObject.isComplete"
></todo-item>
// 자식 컴포넌트
Vue.component('child', {
  props: ['text', 'isComplete'],	// JavaScript에서는 camelCase 사용
  template: '<h3>{{ text }} {{ isComplete }}</h3>'
})

리터럴 vs 동적

흔히 하는 실수는 리터럴 구문을 사용하여 숫자를 전달하려고 시도하는 것이다.
리터럴 prop이기 때문에 그 값은 실제 숫자가 아닌 일반 문자열 "1"로 전달된다.

Number 타입 전달

<!-- 일반 문자열 "1"을 전달 -->
<comp some-prop="1"></comp>

<!-- 숫자를 전달하려면 값이 JavaScript 표현식으로 평가되도록 `v-bind`를 사용 -->
<comp v-bind:some-prop="1"></comp>

Boolean 타입 전달

<!-- 값이 없는 prop은 'true'를 전달 -->
<comp prop-bool></comp>

<!-- JavaScript 표현식 'false'로 값을 전달하려면 `v-bind`를 사용  -->
<comp v-bind:prop-bool="false"></comp>

<!-- 변수의 값을 동적으로 할당 -->
<comp v-bind:prop-bool="bool.propBool"></comp>

단방향 데이터 흐름

모든 props는 상위 속성과 하위 속성 사이의 단방향 바인딩을 형성한다.
상위 속성이 업데이트되면 하위로 흐르게 되지만, 그 반대는 안 된다.

props로 받은 데이터를 변경하고 싶을 경우, 아래 예시에 따른다.

  1. props는 초기값을 전달하기 위해 사용되며,
    하위 컴포넌트는 props를 로컬 데이터 속성으로 사용할 때

    이 경우 propsdata에 정의하는 것이 가장 좋다.

    props: ['initialCounter'],
    data: function () {
     return { counter: this.initialCounter }
    }
  2. props가 변환이 필요한 원시 값으로 전달 될 때
    이 경우 propscomputed에 정의하는 것이 가장 좋다.

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

++ JavaScript의 객체와 배열은 참조로 전달되므로 props가 배열이나 객체인 경우,
하위 객체 또는 배열 자체를 부모 상태로 변경하면 부모 상태에 영향을 준다.

props 검증

컴포넌트가 받는 중인 prop에 대한 요구사항(type, default, validation)을 지정할 수 있다.
지정한 요구사항이 충족 되지 않으면 Vue에서 경고를 보낸다.
이 기능은 다른 사용자가 사용할 컴포넌트를 제작할 때 유용하며,
props문자열 배열로 정의(ex. props: ['text'])는 대신 유효성 검사 요구사항이 있는 객체를 사용할 수 있다.

  • Type : String, Number, Boolean, Array, Object, Date, Function
    Symbol
Vue.component('my-component', {
  props: {
    // 기본 타입 확인
    propA: Number,
    propA_1: null,		// `null`과 `undefined`는 
    propA_2: undefined,	// 어떤 타입이든 가능하다 라는 뜻
    // 여러 개 타입이 가능 (아래의 경우 String, Number만 가능)
    propB: [String, Number],
    // 문자열이며 꼭 필요로 함
    propC: {
      type: String,
      required: true
    },
    // 숫자이며 기본 값(100)을 가짐
    propD: {
      type: Number,
      default: 100
    },
    // 
    propE: {
      type: Object,
      // 객체∙배열의 기본값은 팩토리 함수에서 반환되어야 함
      default: function () {
        return { message: 'hello' }
      }
    },
    // 사용자 정의 유효성 검사
    propF: {
      validator: function (value) {
        return ['success', 'warning', 'danger'].includes(value)
      }
    }
  }
})

props는 컴포넌트 인스턴스가 생성되기 전에 검증된다.
때문에 default, validator 함수 내에서 data, computed, methods 같은 인스턴스 속성을 사용할 수 없다.

type에는 커스텀 생성자가 사용될 수 있다.

function Person (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}
Vue.component('book-post',{
  props: {
    author: Person
  }
})
profile
까먹지마도토도토잠보🐘

0개의 댓글