슬롯은 분명히 중요한 기능이다.
더 많은 유연성을 제공해주고, 슬롯 없이는 할 수 없는 작업을 가능하게 해준다.
아직 슬롯에 관해 다뤄야할 것이 더 있다.
# fallback 기본 컨텐츠 제공
예를 들어, 슬롯에 기본 컨텐츠를 제공할 수 있다.
여기서 '기본'이란 이름(name)이 없는 슬롯을 의미하는건 아니다. 수신하는 컨텐츠가 없는 슬롯에 기본 컨텐츠를 렌더링할 수 있다는 의미.
예를 들어, BaseCard.vue 파일에 header에서 slot태그 사이에 컨텐츠를 추가하여 기본 컨텐츠를 만들 수 있다.
어떻게 작동하는지 보기위해 header태그의 slot 사이에 h2태그로 'The Default'를 추가해보자.
<!--BaseCard.vue-->
<template>
<div>
<header>
<slot name="header">
<h2>The Default</h2>
</slot>
</header>
<slot></slot>
</div>
</template>
기본 컨텐츠가 필요한 컴포넌트도 분명히 있을 수 있다.
컨텐츠를 slot태그 사이에 추가하면 기본값이 된다.
지금은 표시되지 않는다. 왜냐하면 BaseCard.vue 컴포넌트를 사용하는 모든 컴포넌트(BadgeList.vue와 UserInfo.vue 컴포넌트)에 header 슬롯에 컨텐츠를 제공하기 때문.
BadgeList.vue에 v-slot:header 템플릿이 없다고 가정해보자. 즉, BaseCard.vue의 header 슬롯에 어떤 컨텐츠도 제공하지 않는다.
<template>
<base-card>
<!-- <template v-slot:header>
<h2>Available Badges</h2>
</template> -->
<template v-slot:default>
<ul>
<li>
<base-badge type="admin" caption="ADMIN"></base-badge>
</li>
<li>
<base-badge type="author" caption="AUTHOR"></base-badge>
</li>
</ul>
</template>
</base-card>
</template>
그럼 이제 해당 컴포넌트에 'The Default'가 보인다. 슬롯 폴백 컨텐츠인 기본 컨텐츠가 표시되기 때문이다.
이러한 슬롯 기본값은 특정 컴포넌트에서 유용할 수 있다.
특정 컴포넌트에서 유용한지 따져볼 수 있다.
시각적 스타일을 제공하는 wrapper역할을 하는 card에 왜 기본제목이 있어야 할까?
결국 Card에 전달될 컨텐츠가 무엇인지는 모르기 때문에 기본 제목을 렌더링하는것이 아마 적절하다.
# $slots
기본 폴백 컨텐츠를 렌더링하지않으면, BadgeList.vue에서 BaseCard.vue의 header 슬롯에 어떤 컨텐츠도 제공하지 않으면 BadgeList 카드에는 제목이 표시되지 않는다.
하지만 HTML 마크업을 살펴보면 빈 header 요소가 있는게 보인다.
화면에서는 header가 보이지 않지만, 의미적 측면에서는 이상적이진 않다. DOM에 빈 HTML 요소가 있는걸 원하지 않는다.
여기에서 다른 멋진 기능을 활용할 수 있다.
slot을 정의하는 컴포넌트에서 Vue에서 제공하는 특수 프로퍼티가 있다. → 바로 $slots
mounted 생명주기를 추가하면 볼 수 있다.
mounted(){
console.log(this.$slots)
},
$slots은 Vue에서 제공하는 내장 프로퍼티이다. BaseCard 컴포넌트가 다른 slot에 대해 수신하는 슬롯 데이터에 관한 정보를 보유한다.
새로고침을 하면, 두 개의 console.log가 보인다.
왜 두개일까?
왜냐하면 BaseCard.vue는 slot이 UserInfo.vue, BadgeList.vue 이렇게 두 번 사용되기 때문이다.
BaseCard.vue 컴포넌트는 두 번 사용되고 mount되기 때문에, 이 컴포넌트가 사용될 때마다 mounted가 호출된다.
흥미로운 점은 이 객체가 우리가 제공하는 슬롯들에 액세스 할 수 있다는 점이다.
실제로 $slots에서 .header에 액세스 할 수 있다.
이름이 header인 슬롯이 있으므로 .header로 액세스하면 흥미로운 것을 볼 수 있다.
mounted(){
console.log(this.$slots.header)
},
새로고침하면 두 개의 출력이 보인다.
하나는 긴 출력이 하나 있고, 다른 하나는 undefined가 출력된다.
undefined는 BadgeList.vue 컴포넌트에 있는 base-card 컴포넌트 사용에서 나온 출력이다.
여기에서 header 슬롯에 대한 컨텐츠를 제공하지 않기 때문에, BaseCard.vue 컴포넌트에서 제공된 컨텐츠에 액세스하려고하면 BadgeList.vue에 사용될 BaseCard.vue 컴포넌트가 생성될 때 undefined가 출력된다.
이건 이렇게 활용할 수 있다.
header 요소에 v-if를 추가하여 $slots.header가 true인지 확인할 수 있다.
그래서 undefined가 나온다면 아예 header 요소가 렌더링되지 않도록 한다.
<header v-if="$slots.header">
<slot name="header">
<h2>The Default</h2>
</slot>
</header>
개발자도구에서 BadgeList.vue 컴포넌트를 검사하면 header가 아예 없다.
물론 작은 개선일 뿐이지만, 좀 더 발전되었다.
$slots을 사용하여 특정 슬롯에 대한 데이터를 수신하는지 확인하고, 아니라면 해당 정보를 사용해서 특정 요소를 렌더링하지 않을 수 있다.
UserInfo에서는 header 컨텐츠를 제공하므로 UserInfo.vue 컴포넌트에서는 여전히 header를 출력한다.
default 슬롯도 있으니, default에도 액세스할 수 있다.
mounted(){
console.log(this.$slots.default)
},
# v-slot의 축약어
slot을 제공하는 컴포넌트를 사용하는 곳에서, template와 v-slot 디렉티브를 사용해서 slot 컨텐츠를 제공한다.
v-bind, v-on처럼 v-slot에 대한 축약어도 있다. v-slot으로 사용해도 전혀 문제없지만 #기호로 대체할 수 있다.
<template>
<base-card>
<template #header>
<h2>Available Badges</h2>
</template>
<template #default>
<ul>
<li>
<base-badge type="admin" caption="ADMIN"></base-badge>
</li>
<li>
<base-badge type="author" caption="AUTHOR"></base-badge>
</li>
</ul>
</template>
</base-card>
</template>
** 출처: 모든 내용은 Udemy Vue-완벽가이드 강의를 기반으로 작성하였습니다.
'Vue.js' 카테고리의 다른 글
[Udemy Vue 완벽가이드 Section9] 118. 동적 컴포넌트 (component태그) (0) | 2023.08.30 |
---|---|
[Udemy Vue 완벽가이드 Section9] 117. 범위가 지정된(scoped) 슬롯 (0) | 2023.08.30 |
[Udemy Vue 완벽가이드 Section9] 115. 슬롯 스타일 및 컴파일 (0) | 2023.08.30 |
[Udemy Vue 완벽가이드 Section9] 114. 이름이 있는 슬롯(Named Slots) (0) | 2023.08.29 |
[Udemy Vue 완벽가이드 Section9] 113. 슬롯(slots) 소개 (0) | 2023.08.29 |