컴포넌트를 사용하면 UI를 독립적이고 재사용 가능한 일부분으로 분할하고 각 부분을 개별적으로 다룰 수 있음.
따라서 앱이 중첩된 컴포넌트의 트리로 구성되는 것은 일반적임.
이것은 기본 HTML 엘리먼트를 중첩하는 방법과 매우 유사함.
Vue는 각 컴포넌트에 사용자 정의 컨테츠와 논리를 캡슐화할 수 있는 자체 컴포넌트 모델을 구현함.
Vue는 기본 웹 컴포넌트와도 잘 작동함.
빌드 방식을 사용할 때 일반저긍로 싱글 파일 컴포넌트(줄여서 SFC) 라고 하는 .vue
확장자를 사용하는 전용 파일에 각 Vue 컴포넌트를 정의함.
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">당신은 {{ count }} 번 클릭했습니다.</button>
<template>
빌드 방식을 사용 하지 않을 때, Vue 컴포넌트는 Vue 관련 옵션을 포함하는 일반 JavaScript 객체로 정의할 수 있음.
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return { count }
},
template: `
<button @click="count++>
당신은 {{ count }} 번 클릭했습니다.
</button>`
javaScript 문자열로 정의한 템플릿은 Vue가 즉석에서 컴파일함. 엘리먼트(보통 기본 <template>
엘리먼트)를 가리키는 ID 셀렉터를 사용할 수 있음. Vue는 해당 컨텐츠를 템플릿 소스로 사용함.
위의 예는 단일 컴포넌트를 정의하고 이를 .js
파일의 내보내기 기본 값으로 내보냄.
그러나 명명된 내보내기를 사용하여 한 파일에서 여러 개의 컴포넌트로 내보낼 수 있음.
자식 컴포넌트를 사용하려면 부모 컴포넌트에서 가져와야 함. 파일 안에 buttonCounter.vue
라는 카운터 컴포넌트를 배치했다고 가정하면, 해당 컴포넌트 파일의 기본 내보내기가 노출됨.
<script setup>
import ButtonCounter from './ButtonCounter.vue'
</script>
<template>
<h1>아래에 자식 컴포넌트가 있습니다.</h1>
<ButtonCounter />
</template>
<script setup>
을 사용하면 가져온 컴포넌트를 템플릿에서 자동으로 사용할 수 있음.
컴포넌트를 전역으로 등록하면, 가져오기(import) 없이 지정된 앱의 모든 곳에서 컴포넌트를 사용할 수 있음.
전역 및 로컬 등록의 장단점은 컴포넌트 등록 섹션에서 설명함.
컴포넌트는 원하는 만큼 재사용할 수 있음.
<h1>여기에 많은 자식 컴포넌트가 있습니다!</h1>
<ButtonCounter />
<ButtonCounter />
<ButtonCounter />
버튼을 클릭할 때 각 버튼은 독립적인 count
를 유지함
컴포넌트를 사용할 때마다 해당 컴포넌트의 새 인스턴스가 생성되기 때문.
SFC에서는 네이티브 HTML 엘리먼트와 구별하기 위해 자식 컴포넌트에 PascalCase
태그 이름을 사용하는 것이 좋음.
기본 HTML 태그 이름은 대소문자를 구분하지 않지만, Vue의 SFC는 컴파일된 포멧으로 대소문자를 구분하여 태그 이름을 사용할 수 있음. 또한 />
를 사용하여 태그를 닫을 수 있음.
템플릿을 DOM에서 직접 작성하는 경우(ex: 기본 <template>
엘리먼트의 컨텐츠로), 템플릿은 브라우저의 기본 HTML 구문 분석 동작을 따름. 이러한 경우 컴포넌트는 kebab-case
및 명시적 닫는 태그를 사용해야 함.
<!-- 이 템플릿이 DOM에 작성된 경우 -->
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
블로그를 구축하는 경우 블로그 게시물을 나타내는 컴포넌트가 필요할 수 있음.
우리는 모든 블로그 게시물이 동일한 시각적 레이아웃을 공유하기를 원하지만 컨텐츠는 다름.
이러한 곳에 사용할 컴포넌트는 표시하려는 특정 게시물의 제목 및 컨텐츠와 같은 데이터를 전달할 수 없으면 유용하지 않음.
props
가 필요한 건 바로 이때임.
props
는 컴포넌트에 등록할 수 있는 사용자 정의 속성임.
블로그 게시물 제목을 컴포넌트에 전달하려면, defineProps
메크로를 사용해야함.
<!-- BlogPost.vue -->
<script setup>
defineProps(['title'])
</script>
<template>
<h4>{{ title }}</h4>
</template>
defineProps
는 <script setup>
내에서만 사용할 수 있는 컴파일 타임 매크로임, 템플릿에 선언된 props
는 자동으로 노출됨. 그리고 defineProps
는 컴포넌트에 전달된 모든 props
를 객체로 반환하므로, 필요한 경우 JavaScript에서 접근할 수 있음.
import { defineProps } from 'vue'
const props = defineProps(['title'])
console.log(props.title)
부모 컴포넌트에 다음과 같은 게시물 배열이 있을 수 있음
const posts = ref([
{ id: 1, title: 'Vue와 함께한 나의 여행' },
{ id: 2, title: 'Vue로 블로깅하기' },
{ id: 3, title: 'Vue가 재미있는 이유' }
])
그런 다음 v-for
를 사용하여 각각을 컴포넌트로 렌더링 하려고함.
<BlogPost
v-for="post in posts"
:key="post.id"
:title="post.title"
/>