기록/FRONTEND

[Vue] Component

5월._. 2022. 5. 19.
728x90

1. Component

HTML elemet를 확장해 재사용 가능한 코드를 캡슐화한다.

Vue Component는 Vue instance이기도 하기 때문에 모든 옵션 객체를 사용한다. (루트에만 사용하는 옵션 객체는 제외된다.)

Life Cycle Hook도 사용가능하다.

data 옵션은 반드시 함수여야 한다.

 

2. 컴포넌트 등록

컴포넌트 이름은 케밥 표기법을 권장한다. (ex. my-component)

전역 컴포넌트

Vue.component('컴포넌트-이름', {
  template:'<div>사용자 정의 컴포넌트 입니다!</div>'
})

지역 컴포넌트

components 인스턴스 옵션으로 등록함으로써 다른 인스턴스/컴포넌트 범위에서만 사용할 수 있는 컴포넌트를 만들 수 있다.

new Vue({
  // ...
  components: {
    '컴포넌트-이름':'<div>사용자 정의 컴포넌트 입니다!</div>'
  }
})

 

3. 컴포넌트 사용

<div id="example">
  <컴포넌트-이름></컴포넌트-이름>
</div>

아래와 같이 렌더링된다.

<div id="example">
  <div>사용자 정의 컴포넌트 입니다!</div>
</div>

 

4. 컴포넌트 간 통신

오른쪽 이미지는 예시다. 꼭 부모가 #app일 필요는 없다.

상위(부모)와 하위(자식) 컴포넌트 간의 data 전달 방법이다.

부모->자식 : props 전달

자식->부모 : event로만 전달 가능하다.

부모 템플릿의 하위 속성/메소드에 디렉티브를 바인딩하려고하면 안된다.

 

상위에서 하위 컴포넌트로 data 전달 : props

렌더링 과정

  1. new Vue()로 상위 컴포넌트인 인스턴스 생성(이 과정에서 el:"#app"으로 지정했다고 생각한다.)
  2. Vue.component()를 이용해 하위 컴포넌트 child-component생성
  3. <div id="app">내부에서 <child-component>가 있기 때문에 child-component가 하위 컴포넌트가 된다. 따라서 1과 2는 부모 자식 관계가 성립한다.
  4. 하위 컴포넌트의 props 속성을 정의한다.
  5. html에 컴포넌트 태그(child-component)를 추가한다.
  6. 하위 컴포넌트에 v-bind속성을 사용하면 상위 컴포넌트 data의 key에 접근이 가능하다.
  7. 상위 컴포넌트의 message 속성 값이 하위 컴포넌트에 propsdata로 전달된다.
  8. 하위 컴포넌트의 template 속성에 정의된 '<span>{{message}}</span>'에게 전달된다.

 

data 전달

하위 컴포넌트는 상위 컴포넌트의 값을 직접 참조할 수 없다.

data와 마찬가지로 props로 전달된 속성들은 template에서 사용이 가능하다.

Vue.component('하위-컴포넌트-이름', {
  props: ['message'],
  template: '<span>{{ message }}</span>'
})

데이터 전달은 다음과 같은 방식으로 한다.

v-bind를 사용해 props를 동적으로 바인딩할 수도 있다.

<!-- 상위 컴포넌트에서 전달한다. -->
<하위-컴포넌트-이름 message="안녕하세요"></하위-컴포넌트-이름>
<하위-컴포넌트-이름 :message="속성명"></하위-컴포넌트-이름>

+ 리터럴 구문을 사용해 숫자를 전달하려고 하면 안된다. 위는 문자열 "1", 아래는 숫자 1로 전달된다.

<comp some-prop="1"></comp>
<comp v-bind:some-prop="1"></comp>

 

prop 검증

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

type String,Number,Boolean, Function, Object, Array, Symbol 중 하나를 사용할 수 있다. null이면 어떤 타입이든 가능하다는 의미다.
여러 타입이 가능하도록 하려면 배열을 사용한다.
required 꼭 필요한지 지정한다.
default 기본값
validator 사용자 정의 유효성 검사를 한다.
Vue.component('example', {
  props: {
    // 기본 타입 확인 (`null` 은 어떤 타입이든 가능하다는 뜻)
    propA: 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 value > 10
      }
    }
  }
})

 

하위에서 상위 컴포넌트로 data 전달 : emit

하위 컴포넌트에서 상위 컴포넌트가 지정한 이벤트를 발생시킨다.($emit)

상위 컴포넌트는 하위 컴포넌트가 발생한 이벤트를 수신(on)해 data를 처리한다.

//하위컴포넌트
this.$emit("이벤트명");

//상위컴포넌트html
<하위컴포넌트명 v-on:이벤트명="상위컴포넌트메소드명"></하위컴포넌트명>

예제

<div id="counter-event-example">
  <p>{{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>
//하위 컴포넌트
Vue.component('button-counter', {
  template: '<button v-on:click="incrementCounter">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    incrementCounter: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})

//상위 컴포넌트
new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})

'기록 > FRONTEND' 카테고리의 다른 글

[JS] Axios  (0) 2022.05.24
[JS] Module  (0) 2022.05.20
[Vue] Event  (0) 2022.05.18
[Vue] Vue Instance  (0) 2022.05.17
[Vue] Directives  (0) 2022.05.16

댓글