본문 바로가기
PROGRAMMING/Vue

[Vue] Components

by 안녕나는현서 2021. 11. 20.
728x90

Component (컴포넌트)

  • 기본 HTML 엘리먼트를 확장하여 재사용 가능한 코드를 캡슐화하는데 도움을 줌
  • CS에서는 다시 사용할 수 있는 범용성을 위해 개발된 소프트웨어 구성 요소를 의미
  • 유지보수, 재사용성 up
  • Vue 컴포넌트 === Vue 인스턴스

 

SFC (Singel File Component)

  • Vue 컴포넌트 기반 개발의 핵심 특성
  • 하나의 컴포넌트는 .vue 확장자를 가진 하나의 파일 안에서 작성되는 코드의 결과물
  • 화면의 특정 영역에 대한 HTML, CSS, JavaScript 코드를 하나의 파일(.vue)에서 관리
  • Vue 컴포넌트 === Vue 인스턴스 === .vue 파일

 

Vue Component 구조

  • 한 화면 안에서도 기능 별로 각기 다른 컴포넌트 존재 (하나의 컴포넌트는 여러 개의 하위 컴포넌트 가질 수 있음)
  • Vue  component는 const app = new Vue({...})의 app을 의미, 이는 Vue의 인스턴스
    • 컴포넌트 기반 개발이 반드시 파일 단위로 구분되어야 하는 것은 아님!!
    • 단일 .html 파일 안에서도 여러 개의 컴포넌트를 만들어 개발 가능
  • Vue app은 자연스럽게 중첩된 컴포넌트 트리로 구성됨
  • 컴포넌트 간 부모-자식 관계 구성됨
  • 부모는 자식에게 '데이터'를 전달 : pass props
  • 자식은 자신에게 일어난 일을 부모에게 '메시지' 알림 : emit event

 

- 템플릿 (HTML)

  • HTML의 body 부분
  • 각 컴포넌트를 작성

 

- 스크립트 (JavaScript)

  • JavaScript가 작성되는 곳
  • 컴포넌트 정보, 데이터, 메서드 등 vue 인스턴스를 구성하는 대부분이 작성됨

 

- 스타일 (CSS)

  • CSS가 작성되며 컴포넌트 스타일을 담당

 

Component 등록

<!-- Parent.vue --> 

<template>
  <div>
    <!-- 3. 보여주기 -->
    <!-- <child></child> -->
    <child/>
  </div>
</template>

<script>
// 1. 불러오기
import Child from '@/components/Child.vue'

export default {
  name: 'Parent',
  components: {
    // 2. 등록하기
    Child
  },
}
</script>

 

 

Props

  • 부모(상위) 컴포넌트의 정보(데이터)를 전달하기 위한 사용자 지정 특성
  • 자식(하위) 컴포넌트는 props 옵션을 사용하여 수신하는 props를 명시적으로 선언해야 함
  • 모든 컴포넌트 인스턴스에는 자체 격리된 범위가 있음 (자식 컴포넌트 템플릿에서 상위 데이터를 직접 참조 불가)
  • props 이름 컨벤션
    • during declaration (선언 시) : camelCase
    • in template (HTML) : kebab-case

 

1. 자식 컴포넌트에 보낼 props 데이터 선언

<!-- Parent.vue --> 

<template>
  <div>
    <!-- 작성법 : prop-data-name="value" -->
    <child
      my-message="Hello!"
    />
  </div>
</template>

<script>
import Child from '@/components/Child.vue'

export default {
  name: 'Parent',
  components: {
    Child
  },
}
</script>

 

2. 수신할 데이터를 명시적으로 선언 후 사용

<!-- Child.vue --> 

<template>
  <div>
    <!-- 사용 -->
    <p>{{ myMessage }}</p>
  </div>
</template>

<script>
import Child from '@/components/Child.vue'

export default {
  name: 'Child',
  // 선언
  props: {
    myMessage: String,
  },
}
</script>

 

- 동적으로 props 작성하기

<!-- Parent.vue --> 

<template>
  <div>
    <child
      :my-message="Hello!"
    />
  </div>
</template>

<script>
import Child from '@/components/Child.vue'

export default {
  name: 'Parent',
  components: {
    Child
  },
  data: function () {
    return {
      myMessage: 'This is parent Data by v-bind'
    }
  },
}
</script>
  • v-bind directive를 사용해 부모 데이터의 props를 동적으로 바인딩
  • 부모에서 데이터가 업데이트 될 때마다 자식 데이터로도 전달
  • 컴포넌트의 data는 반드시 함수여야 함!
    • 기본적으로 각 인스턴스는 모두 같은 data 객체를 공유하므로 새로운 data 객체를 반환해야 함
    • 그렇지 않으면 각 인스턴스가 모두 같은 data 객체를 공유하게 됨
  • props시 숫자를 전달하려면 v-bind를 사용해야함
<!-- 일반 문자열 "1"을 전달 -->
<comp some-prop="1" />

<!-- 실제 숫자로 전달 -->
<comp :some-porp="1" />

 

Emit event

  • 모든 props는 하위 속성과 상위 속성 사이의 단방향 바인딩 형성
  • 부모의 속성이 변경되면 자식 속성에게 전달되지만, 반대 방향으로는 안 됨
    (자식 요소가 부모 요소의 상태를 변경하는 경우 방지)
  • $emit(eventName)
    • 현재 인스턴스에거 이벤트를 트리거
    • 추가 인자는 리스너의 콜백 함수로 전달
  • 부모 컴포넌트는 자식 컴포넌트가 사용되는 템플릿에서 v-on을 사용하여 자식 컴포넌트가 보낸 이벤트 청취
  • event 이름 컨벤션
    • 컴포넌트, props와 달리 자동 대소문자 변환 제공 x
    • HTML의 대소문자 구분을 위해 DOM 템플릿의 v-on 이벤트 리스너는 항상 소문자로 변환
    • 이러한 이유로 이벤트 이름은 항상 kebab-case

 

1. $emit 인스턴스 메서드 사용하여 이벤트 트리거

<!-- Child.vue --> 

<template>
  <div>
    <input
      @keyup.enter="ChildInputChange"
      v-model="childInput"
    >
  </div>
</template>

<script>
import Child from '@/components/Child.vue'

export default {
  name: 'Child',
  data: {
    return {
      childInput: null,
    }
  },
  props: {
    myMessage: String,
  },
  methods: {
    childInputChange: function () {
      this.$emit('child-input-change', this.childInput)
    },
  },
}
</script>

 

2. 부모 컴포넌트는 자식 컴포넌트가 사용되는 템플릿에서 v-on를 사용하여 이벤트 청취

<!-- Parent.vue --> 

<template>
  <div>
    <child
      :my-message="Hello!"
      @child-input-change="parentGetChange"
    />
  </div>
</template>

<script>
import Child from '@/components/Child.vue'

export default {
  name: 'Parent',
  components: {
    Child
  },
  data: function () {
    return {
      myMessage: 'This is parent Data by v-bind'
    }
  },
  methods: {
    parentGetChange: function (inputData) {
      console.log(`Child로부터 ${inputData} 받음!`)
    },
  },
}
</script>
728x90

'PROGRAMMING > Vue' 카테고리의 다른 글

[Vue] Router  (0) 2021.11.21
[Vue] Vue CLI  (0) 2021.11.20
[Vue] Lifecycle Hooks, lodash  (0) 2021.11.15
[Vue] Template Syntax  (0) 2021.11.15
[Vue] MVVM Pattern, Vue 인스턴스 생성  (0) 2021.11.15

댓글