이전 포스트에서 부모 컴포넌트에서 자식 컴포넌트로 값(데이터)을 전달하기 위해서 props를 사용하는 것에 대해서 살펴보았다. 이번에는 props와 유사하지만 값이 아닌 html markup을 전달하려는 경우에 필요한 slot이라는 것에 대해서 살펴보자.
<slot>
slot의 필요성
props를 통해서 부모 컴포넌트에서 자식 컴포넌트로 전달할 수 있는 것은 JavaScript의 타입(String, Number, Object, ...)의 데이터 들이다. 전달받은 데이터를 어떻게 사용할지(computed로 하건, local 변수에 할당하건, 스타일을 어떻게 적용하건)는 오롯이 자식 컴포넌트의 몫이다.
그런데 만약 html markup이 전달된다면 어떨까? 문자를 파싱해서 어떤 태그인지 확인해야 하고 태그 중간에 데이터는 무엇인지, 어떤 스타일을 적용해야 할 것인지 처리하기가 매우 복잡할 것이다.
이런 경우 유용한 것이 slot인데 <slot>은내용을 어떻게 표현해야할지 부모 컴포넌트가 잘 알고 있을 때 매우 유리하다.
<slot>기본 사용법
<slot>은자식 컴포넌트에서 <slot>을 선언하면부모 컴포넌트에서 <slot>에 들어갈 markup을 공급해 주는 방식이다. 다음의 그림은 props와 slot을 같이 사용하면서 그 차이를 확인해 보기에 아주 유용하다.
자식 컴포넌트에 props로 선언된 title이나 from은 부모가 일단 넘겨주면 다음은 자식 컴포넌트가 어떻게 보일지 결정한다. 하지만 slot의 경우는 자식은 <slot>이라고 자리만 표시하면 되고 거기에 어떤 데이터가 어떻게 표현될지는 모두 부모 컴포넌트가 결정하다.
이처럼 <slot>을 사용하면 뷰 컴포넌트를 훨씬 유연하게 재사용 가능하게 할 수 있다.
이처럼 <slot>이 적용되면 화면이 변경된다고 해서 MessageBox2를 새로 작성할 필요가 없어진다.
named slot
named slot
named slot은 말 그대로 이름이 있는 slot으로하나의 component에 여러 개의 <slot>이 있어서 이들을 구별할 필요가 있을 때사용된다.
<slot>을사용할 때에는v-slot:name으로 slot을 지정한다.v-slot 디렉티브는 custom tag에만 사용할 수 있기 때문에 html 내용을<template>으로 묶어 주어야 한다.v-slot에 대한 축약형으로 #을 사용할 수 있다. 만약 v-slot을 생략할 때에는 이름없는 <slot>에 연결된다.
기본적으로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> 사이에 필요한 내용을 구성해 주면 된다.