Vue - 컴포넌트 재 사용을 위한 slot

김규빈·2021년 1월 17일
1
post-custom-banner

Vue- slot을 마주한 순간🤯

실제로 스토어링크 관리자 페이지를 리팩토링 중인 코드에는 slot이 엄~청 많다.
하지만 Vue 공식문서를 보니 <v-slot는 slot과 slot-scope 인수들을 대체하게 되었습니다, 더 발전된 API로 Vue 2.6.0에 도입되었고, slot과 slot-scope 인수는 앞으로도 2.x 버전에서는 계속 지원될 것입니다. 하지만 Vue 3에서는 공식적으로 삭제될 예정입니다.> 라고 나와있다. 리팩토링이 필요한 부분인 것 같다.

Slot

슬롯(slot)은 컴포넌트의 재사용성을 높여주는 기능이다. 특정 컴포넌트에 등록된 하위 컴포넌트의 마크업을 확장하거나 재정의할 수 있다는데...

<template>
  <div class="tab panel">
    <!-- 탭 헤더 -->
    <slot></slot>
    <!-- 탭 본문 -->
    <div class="content">
      Tab Contents
    </div>
  </div>
</template>

위 코드는 ButtonTab 컴포넌트의 코드입니다. 탭을 구현한다고 생각하고 탭 헤더와 본문을 구분하는 태그를 작성하였습니다. 여기서 탭 헤더에 들어갈 구체적인 태그를 정하지 않고 일단 slot 태그로 빈 칸을 남겨놉니다. 만약 이 컴포넌트를 등록한 상위 컴포넌트에서 slot 태그 영역을 구현하지 않으면 해당 부분은 공백으로 표시됩니다.

slot 태그의 위치에 주목하면서 ButtonTab 컴포넌트를 TabContainer 컴포넌트의 하위 컴포넌트로 등록합니다.

<template>
<button-tab>
  <!-- slot 영역 -->
  <h1>First Header</h1>
</button-tab>
<button-tab>
  <!-- slot 영역 -->
  <h1>Second Header</h1>
</button-tab>
<button-tab>
  <!-- slot 영역 -->
  <h1>Third Header</h1>
</button-tab>
</template>

<script>
export default {
components: {
  ButtonTab
}
}
</script>

TabContainer 컴포넌트에 ButtonTab 컴포넌트를 등록하고 ButtonTab 컴포넌트를 세 곳에 표시했습니다. 여기서 button-tab 컴포넌트 태그의 안에 각기 다른 헤더의 내용을 정의했습니다. 만약 ButtonTab 컴포넌트에 slot 태그를 정의하지 않았다면 컴포넌트를 등록하는 시점에 마크업을 재정의할 수는 없었을 것입니다.

이처럼 슬롯을 사용하면 컴포넌트의 특정 마크업 영역을 재정의하여 같은 컴포넌트를 각기 다르게 표현할 수 있습니다.

Slot -name

<template>
  <div class="tab panel">
    <!-- 탭 헤더 -->
    <slot name="header"></slot>
    <!-- 탭 본문 -->
    <slot name="content"></slot>
  </div>
</template>

name으로 각 컴포넌트를 달리해서 사용할 수 있게 된다.

<template>
  <button-tab>
    <!-- slot 영역 -->
    <h1 slot="header">First Header</h1>
    <div slot="content" class="content">Tab Contents #1</div>
  </button-tab>
  <button-tab>
    <!-- slot 영역 -->
    <h1 slot="header">Second Header</h1>
    <div slot="content" class="content">Tab Contents #2</div>
  </button-tab>
  <button-tab>
    <!-- slot 영역 -->
    <h1 slot="header">Third Header</h1>
    <div slot="content" class="content">Tab Contents #3</div>
  </button-tab>
</template>

새로 도입된 v-slot

<div class="container">
  <header>
    <!-- 헤더는 여기에 넣을 겁니다 -->
  </header>
  <main>
    <!-- 본문은 여기에 넣을 겁니다 -->
  </main>
  <footer>
    <!-- 푸터는 여기에 넣을 겁니다 -->
  </footer>
</div>

이러한 구조의 템플릿에서

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

slot 에 name의 속성을 추가한뒤, 꺼내 쓰는 방식으로 slot을 정의하고

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

v-slot : name을 통해 name에 맞는 slot을 꺼내 사용 할 수 있다. name을 지정하지 않은 slot은 default 값으로 지정이 된다.

결과적으로 렌더링 된 코드는

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

이렇게 된다. 삭제될 예정인 slot 속성과 다르게 v-slot만 template 태그에 추가할 수 있다는 점을 유의하여 사용해야된다. 그리고 축약 문법도 있는데 예를 들어 v-slot:header는 #header로 쓸 수도 있다.

profile
FrontEnd Developer
post-custom-banner

0개의 댓글