Vue 3.0/04.Component

[vue 3] 06. 컴포넌트간 통신 - slot

  • -

이전 포스트에서 부모 컴포넌트에서 자식 컴포넌트로 값(데이터)을 전달하기 위해서  props를 사용하는 것에 대해서 살펴보았다. 이번에는 props와 유사하지만 값이 아닌 html markup을 전달하려는 경우에 필요한 slot이라는 것에 대해서 살펴보자.

 

<slot>

 

slot의 필요성

props를 통해서 부모 컴포넌트에서 자식 컴포넌트로 전달할 수 있는 것은 JavaScript의 타입(String, Number, Object, ...)의 데이터 들이다. 전달받은 데이터를 어떻게 사용할지(computed로 하건, local 변수에 할당하건, 스타일을 어떻게 적용하건)는 오롯이 자식 컴포넌트의 몫이다.

그런데 만약 html markup이 전달된다면 어떨까? 문자를 파싱해서 어떤 태그인지 확인해야 하고 태그 중간에 데이터는 무엇인지, 어떤 스타일을 적용해야 할 것인지 처리하기가 매우 복잡할 것이다.

const fromParent1 = '홍길동'
const fromParent2 = "<span id='name'>장길산</span>"

이런 경우 유용한 것이 slot인데  <slot>은 내용을 어떻게 표현해야할지 부모 컴포넌트가 잘 알고 있을 때 매우 유리하다.

 

<slot>기본 사용법

<slot>은 자식 컴포넌트에서 <slot>을 선언하면 부모 컴포넌트에서 <slot>에 들어갈 markup을 공급해 주는 방식이다. 다음의 그림은 props와 slot을 같이 사용하면서 그 차이를 확인해 보기에 아주 유용하다.

자식 컴포넌트에 props로 선언된 title이나 from은 부모가 일단 넘겨주면 다음은 자식 컴포넌트가 어떻게 보일지 결정한다. 하지만 slot의 경우는 자식은 <slot>이라고 자리만 표시하면 되고 거기에 어떤 데이터가 어떻게 표현될지는 모두 부모 컴포넌트가 결정하다.

이처럼 <slot>을 사용하면 뷰 컴포넌트를 훨씬 유연하게 재사용 가능하게 할 수 있다. 

일관된 MessageBox 에 상황에 따른 화면 구성 가능

이처럼 <slot>이 적용되면 화면이 변경된다고 해서 MessageBox2를 새로 작성할 필요가 없어진다.

 

named slot

 

named slot

named slot은 말 그대로 이름이 있는 slot으로 하나의 component에 여러 개의 <slot>이 있어서 이들을 구별할 필요가 있을 때 사용된다. 

이를 위해 <slot>을 선언할 때 name 속성으로 이름을 지정해 주면 된다.

<template>
  <h1>여러개의 slot 사용하기</h1>

  <slot name="header"></slot>
  <hr />

  <slot name="main"></slot>
  <hr />

  <slot name="footer"></slot>
</template>

 

<slot>을 사용할 때에는 v-slot:name으로 slot을 지정한다. v-slot 디렉티브는 custom tag에만 사용할 수 있기 때문에 html 내용을 <template>으로 묶어 주어야 한다. v-slot에 대한 축약형으로 #을 사용할 수 있다. 만약 v-slot을 생략할 때에는 이름없는 <slot>에 연결된다.

좀 독특한 점은 뭔가 속성을 선언하고 값을 지정하지 않은 느낌이다. 값은 언제쓰지?

  <MultiSlot>
    <template v-slot:header>
      <h1>header</h1>
    </template>

    <template v-slot:main>
      <div>
        <h2>본문</h2>
        <div>본문내용</div>
      </div>
    </template>

    <template #footer>
      <div>footer</div>
    </template>
  </MultiSlot>

slot에서 자식 컴포넌트의 상태값 활용

 

slot과 props

기본적으로 slot 컨텐트는 부모 컴포넌트에서 만들어지기 때문에 부모 컴포넌트의 상태값에만 접근할 수 있고 자식 컴포넌트의 상태값은 사용할 수 없다.

하지만 자식 컴포넌트의 값이 필요하다면 직접 접근할 수는 없지만 props를 통해 공급 받아서 사용할 수는 있다. <slot>을 선언한 자식이 오히려 부모 역할을 하고 부모에서 공급되는 slot data가 자식이 되는 느낌이다.

이를 위해서 자식 컴포넌트와 조상 컴포넌트에서 해야 할 일들을 정리해 보자.

  • 부모 컴포넌트: 부모 컴포넌트에서는 props를 전달받기 위해 컴포넌트 선언부에 v-slot 속성을 사용한다. v-slot은 named component에서 썼던 directive인데 여기서는 컴포넌트의 이름을 지정하기 위한 것외에 자식 컴포넌트가 전달한 props 객체를 할당받는 역할도 수행한다. 여기서 sp는 자식이 전달해준 props 객체이다. 
  • 자식 컴포넌트: 자식 컴포넌트 <slot>에 property 형태로 전달하려는 상태값을 전달해 준다. 위 예에서는 user-name과 user-age를 props 객체에 담아서 전달하는데 이 값이 부모 컴포넌트의 v-slot 값으로 전달된다.

 

기타

 

fallback content

<slot>을 지정해서 부모 컴포넌트로부터 html 내용을 전달받아서 사용할 계획이지만 가끔은 부모 컴포넌트가 아무 값도 주지 않는 상황이 있을 수 있다. 이때는 대체 컨텐트(fallback content)가 사용되는데 <slot>과 </slot> 사이에 필요한 내용을 구성해 주면 된다.

<template>
  <div>
    <slot name="fallback"> 
        <div>부모가 아무것도 안줬다면 이거라도</div> 
    </slot>
  </div>
</template>
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.