조아마시

쓸모 있는 상세페이지 만들기

웹개발/vuejs

[Vue] Vue3에서 slot 사용하기

joamashi 2024. 7. 30. 00:34

Slot은 부모 컴포넌트에서 자식 컴포넌트로 콘텐츠를 전달하는 방법입니다. 부모 컴포넌트는 Slot을 정의하고, 자식 컴포넌트는 이 Slot에 콘텐츠를 채워 넣을 수 있습니다. 이를 통해 컴포넌트를 더욱 유연하게 만들고, 재사용성을 높일 수 있습니다.

Composition API에서 Slot 사용하기

Composition API에서 Slot을 사용하는 방법은 다음과 같습니다.

  1. template에서 Slot 정의:
    • template 옵션에서 <slot> 태그를 사용하여 Slot을 정의합니다.
    • Slot에 이름을 지정하여 다양한 Slot을 관리할 수 있습니다.
  2. setup 함수에서 Slot 전달:
    • setup 함수에서 Slot을 props처럼 자식 컴포넌트로 전달합니다.
    • withDefaults 함수를 사용하여 기본값을 설정할 수 있습니다.

실제 예시

<template>
  <div>
    <MyComponent>
      <template #header>
        <h2>Custom Header</h2>
      </template>
      <p>Slot Content</p>
    </MyComponent>
  </div>
</template>

<script setup>
import MyComponent from './MyComponent.vue';

defineProps({
  // 다른 props 정의
});
</script>
MyComponent.vue
<template>
  <div>
    <slot name="header" />
    <slot />
  </div>
</template>

<script setup>
defineProps({
  // 다른 props 정의
});
</script>
 

위 예시에서 MyComponentheader라는 이름의 Slot을 정의하고 있습니다. 부모 컴포넌트는 template #header를 사용하여 이 Slot에 콘텐츠를 채워 넣습니다.

다양한 Slot 활용 방법

  • Named Slots: 이름을 지정하여 다양한 Slot을 관리할 수 있습니다.
  • Scoped Slots: 부모 컴포넌트에서 자식 컴포넌트의 데이터를 사용할 수 있도록 해줍니다.
  • Default Slots: 이름이 없는 Slot으로, 다른 Slot이 채워지지 않을 때 사용됩니다.

장점

  • 컴포넌트 재사용성 증가: Slot을 사용하면 컴포넌트의 내부 구조를 변경하지 않고도 다양한 콘텐츠를 표현할 수 있습니다.
  • 유연성 향상: 부모 컴포넌트에서 자식 컴포넌트의 렌더링을 완전히 제어할 수 있습니다.
  • 코드 가독성 향상: 컴포넌트의 역할을 명확하게 분리하여 코드를 더욱 이해하기 쉽게 만들 수 있습니다.

다양한 Slot 활용 예시를 통한 이해 심화

앞서 Composition API를 활용한 Slot의 기본 개념과 간단한 예시를 살펴보았습니다. 이번에는 더욱 다양하고 실제적인 예시를 통해 Slot의 활용 범위를 넓혀보겠습니다.

1. Named Slots를 활용한 복잡한 레이아웃 구성

<template>
  <MyComponent>
    <template #header>
      <h1>Custom Header</h1>
    </template>
    
    <template #default>
      <p>Default content</p>
    </template>
    
    <template #footer>
      <p>Custom Footer</p>
    </template>
  </MyComponent>
</template>
<template>
  <div>
    <slot name="header" />
    <slot />
    <slot name="footer" />
  </div>
</template>
  • 설명: header, default, footer와 같이 다양한 이름의 Slot을 정의하여 복잡한 레이아웃을 구성할 수 있습니다. 부모 컴포넌트는 각 Slot에 맞는 콘텐츠를 채워 넣어 자유롭게 레이아웃을 커스터마이징할 수 있습니다.

2. Scoped Slots를 활용한 데이터 전달 및 조건부 렌더링

<template>
  <MyComponent :items="items">
    <template #item="{ item }">
      <li v-if="item.isActive">Active: {{ item.name }}</li>
      <li v-else>Inactive: {{ item.name }}</li>
    </template>
  </MyComponent>
</template>
<template>
  <ul>
    <slot name="item" v-for="item in items" :item="item" />
  </ul>
</template>
  • 설명: scoped slots를 사용하여 부모 컴포넌트의 데이터를 Slot 내부에서 사용할 수 있습니다. v-slot 디렉티브를 통해 전달된 item 객체를 사용하여 조건부 렌더링이나 데이터 가공을 수행할 수 있습니다.

3. Dynamic Slots를 활용한 동적인 Slot 생성

<template>
  <MyComponent :slots="['header', 'footer']">
    </MyComponent>
</template>
 
<template>
  <div>
    <slot v-for="slotName in slots" :name="slotName" />
  </div>
</template>
  • 설명: slots prop을 통해 동적으로 Slot 이름을 생성하고 렌더링할 수 있습니다. 이를 통해 컴포넌트의 구성을 더욱 유연하게 만들 수 있습니다.

4. Slot의 중첩

<template>
  <MyComponent>
    <template #header>
      <p>Header</p>
      <slot name="subHeader" />
    </template>
  </MyComponent>
</template>
  • 설명: Slot 내부에 또 다른 Slot을 정의하여 Slot을 중첩할 수 있습니다. 이를 통해 더욱 복잡한 컴포넌트 구조를 만들 수 있습니다.

Slot 활용 시 주의사항

  • Slot의 이름 충돌: 동일한 이름의 Slot이 여러 개 존재하면 예상치 못한 결과가 발생할 수 있습니다.
  • Scoped Slots의 오용: Scoped Slots는 데이터 전달을 위한 것이지, 컴포넌트 로직을 복잡하게 만드는 데 사용해서는 안 됩니다.
  • Slot의 과도한 사용: Slot을 너무 많이 사용하면 코드 가독성이 떨어질 수 있습니다.
728x90