[Vue3] 컴포넌트 기초

Dohee Kang·2023년 3월 4일
0

Vue

목록 보기
14/28
post-custom-banner

1. 컴포넌트

  • UI를 독립적이고 재사용 가능한 각각의 독립된 모듈

2. 컴포넌트 정의

  • 일반적으로 싱글 파일 컴포넌트(Single File Component; SFC)라고 하는 .vue 확장자를 사용해 각 파일에 해당 컴포넌트를 정의한다.
  • 자식 컴포넌트를 사용하려면 부모 컴포넌트에서 가져와야 한다.
    • (e.g. 부모 컴포넌트 : App.vue, 자식 컴포넌트 : ChildComponent.vue)
  • 자식 컴포넌트를 가져와 템플릿에 정의하려면 <scripts> 안에서 components 옵션을 통해 등록해야 한다.
  • 아래 예시처럼 동일한 여러개의 자식 컴포넌트를 부모 컴포넌트에 선언하여도 자식 컴포넌트는 독립적이다.
    • 컴포넌트를 사용할 때마다 해당 컴포넌트의 새 인스턴스가 생성되기 때문이다.
  • Vue의 SFC는 HTML 엘리먼트(e.g. <div>)와 구별하기 위해 PascaslCase 태그명을 사용하는게 좋다.
<!-- App.vue -->
<template>
  <h1>아래에 자식 컴포넌트가 있습니다.</h1>
  <ChildComponent />
  <ChildComponent />
  <ChildComponent />
</template>

<script>
import ChildComponent from './components/ChildComponent.vue'

export default {
  name: 'App',
  components: {
    ChildComponent
  }
}
</script>

<!-- ChildComponent.vue -->
<template>
  <p>{{ data }}</p>
</template>

<script>
export default {
  data() {
    return {
      data: '자식 컴포넌트'
    }
  }
}
</script>

3. Props 전달

  • 컴포넌트의 같은 데이터를 전달하여 재사용한다면 컴포넌트는 유용하지 않을 것이다.
  • props를 통해 사용자가 컴포넌트에 속성을 정의할 수 있다.
  • 자식 컴포넌트의 <script> 안에서 props를 정의하면 된다.
    • e.g. BlogPost.vue에서 propstitle을 정의하고, App.vue<template>안에서 <BlogPost> 컴포넌트에 :title을 통해 데이터를 전달한다.
<!-- App.vue -->
<template>
  <h1>Blog</h1>
  <ul>
    <BlogPost v-for="post in posts" :key="post.index" :title="post.title" />
  </ul>
</template>

<script>
import BlogPost from './components/BlogPost.vue'
  
export default {
  components: {
    BlogPost
  },
  data() {
    return {
      posts: [
        { title: 'Vue와 함께한 나의 여행' },
        { title: 'Vue로 블로깅하기' },
        { title: 'Vue가 재미있는 이유' }
      ]
    }
  }
}
</script>

<!-- BlogPost.vue -->
<template>
  <li>{{ title }}</li>
</template>

<script>
export default {
  props: ['title']
}
</script>

4. 이벤트 청취

자식 컴포넌트에 이벤트를 등록하고 부모 컴포넌트에 데이터 속성을 추가하여 상위 항목과 다시 통신하는 기능을 사용해보려고 한다.

  • 위 블로그 예제의 부모 컴포넌트에서 postFontSize 데이터 속성을 추가한다.
data() {
  return {
    posts: [
      /* ... */
    ],
    postFontSize: 1
  }
}
  • 부모 컴포넌트에서 <ul> 엘리먼트에 :style 속성을 추가하여 fontSize를 정의한다.
<ul :style="{ fontSize: `${postFontSize}em`}">
    <BlogPost v-for="post in posts" :key="post.index" :title="post.title" @enlarge-text="postFontSize += 0.1"/>
</ul>
  • 자식 컴포넌트의 <template>에 버튼을 추가한다.
<template>
  <li>{{ title }}</li>
  <button type="button">텍스트 확대</button>
</template>
  • 자식 컴포넌트에 버튼을 만들긴 했지만 이벤트 생성은 하지 않았다. 버튼을 클릭할 때 블로그 제목의 텍스트를 확대한다는 커스텀 이벤트 시스템을 만들어야 한다.
    • 커스텀 이벤트 시스템 : 자식 컴포넌트에서 부모 컴포넌트까지 이벤트를 전달하고 싶을 때 자식은 부모의 데이터를 직접 수정할 수 없으므로 커스텀 이벤트 시스템을 통해 부모 데이터 수정해달라고 요청하는 것
  • 부모 컴포넌트는 v-on 또는 @를 사용하여 자식 컴포넌트 인스턴스의 모든 이벤트를 수신하도록 할 수 있다.
<BlogPost
  ...
  @enlarge-text="postFontSize += 0.1"
/>
  • 자식 컴포넌트는 $emit 메서드를 통해 이벤트명을 전달하여 자체적으로 이벤트를 생성할 수 있다.
  • <script> 안에 emits 속성을 통해 이벤트를 선언할 수 있다.
<template>
  <li>{{ title }}</li>
  <button type="button" @click="$emit('enlarge-text')">텍스트 확대</button>
</template>

<script>
export default {
  props: ['title'],
  emits: ['enlarge-text']
}
</script>
profile
오늘은 나에게 어떤 일이 생길까 ✨
post-custom-banner

0개의 댓글