slot은 중요한 기능이다.
slot에 관해 한가지 더 알아보자.
심화기능이지만, 알고 있으면 좋다.
CourseGoals.vue라는 새로운 컴포넌트를 만들어보자.
<!--CourseGoals.vue-->
<template>
<ul>
<li v-for="goal in goals" :key="goal">{{ goal }}</li>
</ul>
</template>
<script>
export default {
data() {
return {
goals: ["Finish the course", "Learn Vue"],
};
},
};
</script>
App.vue로 가서 새로 생성한 CourseGoals.vue 컴포넌트를 불러온다. CourseGoals.vue를 지역 컴포넌트로 등록하면 이제 template에서 사용할 수 있다.
<course-goals></course-goals> 이렇게 입력한다.
이렇게 아래 CourseGoals 컴포넌트가 화면에 출력된다.
이 화면이 slot과 어떤 관련이 있을까?
CourseGoals.vue 컴포넌트는 'goals' 데이터를 포함하고, 관련해서 더 많은 로직을 가질 수 있다.
그리고 그 goals를 화면에 렌더링한다.
여기서 사용자 정의할 수 있는 요소가 하나 있다. 바로 li 항목의 컨텐츠.
예를 들어 li항목이 text로만 이루어져있다면, h2태그를 가지거나 다른 요소들을 가질 수 있는데 그 부분을 사용자가 원하는대로 지정할 수 있게 만들고싶다.
<li v-for="goal in goals" :key="goal">
<h2></h2> <!--h2, p부분을 사용자가 원하는대로.-->
<p></p>
</li>
CourseGoals.vue 컴포넌트를 앱의 다른부분에서 사용할 수도 있는데, 요소를 사용할 때 마다 li항목의 컨텐츠가 달라도 된다.
이를 위해 slot을 사용할 수 있다.
여기에 slot을 넣으면, CourseGoals.vue 컴포넌트를 사용하는 컴포넌트에서 HTML 마크업인 컨텐츠가 li 항목에 전달되고, CourseGoals.vue가 사용되는 장소 내에서 정의된다.
<!--CourseGoals.vue 컴포넌트-->
<li v-for="goal in goals" :key="goal">
<slot></slot>
</li>
예를 들어, App.vue에서 course-goal를 사용하고 있으므로 course-goals에 대한 컨텐츠를 전달할 수 있다.
그러면 h2 마크업이 CourseGoals.vue 컴포넌트의 slot 부분으로 전달된다.
<!--App.vue 컴포넌트-->
<course-goals>
<h2></h2>
</course-goals>
이렇게 마크업을 전달할 수 있지만, 문제가 하나 있다.
바로 li항목이 렌더링되는 개별 goal에 접근할 수 없다는 것. slot 부분으로 전달되면 아래와 같이 구현되는데 여기서 h2태그는 goal에 접근할 수가 없다.
<!--CourseGoals.vue 컴포넌트-->
<li v-for="goal in goals" :key="goal">
<h2></h2>
</li>
goal 변수는 오직 CourseGoals.vue에서 사용할 수 있는데, <slot></slot>에 출력되어야하는 마크업은 App.vue에서 전달된다.
App.vue에서는 CourseGoals.vue에 있는 goal 변수에 접근할 수없다.
이런 식으로 slot을 구축하는 경우, Vue에서 사용할 수 있는 또다른 기능이 있다.
→ 바로 범위가 지정된(scoped) 슬롯.
이 개념은 'slot을 정의한 컴포넌트 내부(CourseGoals.vue)'에서 'slot에 대한 마크업을 전달한 컴포넌트(App.vue)'에 데이터를 전달할 수 있게 한다.
이를 위해 data를 가진 컴포넌트에서, 즉 slot을 정의한 컴포넌트(CourseGoals.vue)에서 slot에 prop을 정의한다.
이름은 원하는대로 지으면 된다. 여기서는 'item', 'another-prop'으로 지었다.
<li v-for="goal in goals" :key="goal">
<slot :item="goal" another-prop="..."></slot>
</li>
반복할 때마다 생성되는 goal을 item에 전달한다.
slot 요소 내에서 설정한 props는 이제 slot에 대한 데이터를 전달하는 곳에서 접근할 수 있게 된다.
이 경우, slot에 마크업을 전달하는 App.vue 이다.
1/ 데이터를 접근하기 위해서는 slot에 대한 마크업을 template으로 감싼다. slot에 보내고 싶은 마크업을 감싼다. template에 v-slot 또는 축약어(#)를 default 슬롯에 사용할 수 있다.
Named slot에도 같은 개념이 적용된다.
2/ 그리고 원하는 이름으로 정의할 수 있다. → 'slotProps'라고 해보자. 원하는 이름을 지으면 된다.
Vue에서 사용하는 변수의 이름으로, 이 변수의 값은 언제나 '객체'이다.
CourseGoals.vue에서 정의한 모든 props가 병합된 객체. 그래서 데이터를 가진 'another-prop'도 slotProps객체의 프로퍼티가 되고, 'another-prop'이란 key로 접근할 수 있다.
slotProps의 값은 { item: 'Finish the course', 'another-prop': '...' } 이렇게다.
3/ 이제 slotProps로 무엇을 할 수 있을까?
이 template 안에서 사용할 수 있다. h2 태그 사이에 보간법을 적용하고, slotProps.item으로 접근한다.
CourseGoals.vue 파일의 slot에서 item prop을 추가했기 때문에 .item으로 접근한다.
item 외에 다른 이름으로 정의했다면, 해당 이름을 slotProps 뒤에 적으면 된다.
<course-goals>
<template #default="slotProps">
<h2>{{ slotProps.item }}</h2>
<p>{{ slotProps['another-prop']}}</p><!--또는 slotProps[anotherProp]도 ok.-->
</template>
</course-goals>
심화 기능이고 자주 사용되지 않는 기능이지만, 이 기능이 없다면 구축하고자 하는 것을 구축할 수 없는 특정 상황이 있다.
위 코드를 간단하게 하는 방법이 있는데, default 슬롯과 같이 하나의 슬롯만을 대상으로 할 때, template을 삭제할 수 있다.
불필요한 template wrapper를 삭제하고, #default="slotProps"를 컴포넌트 태그에 직접 넣는다.
여는태그와 닫는 태그 사이에 마크업이 하나의 슬롯에만 해당할 경우에만 적용된다. 이 경우, default 슬롯 하나만 있어서 간단하게 할 수 있다.
<course-goals #default="slotProps">
<h2>{{ slotProps.item }}</h2>
<p>{{ slotProps.anotherProp }}</p>
</course-goals>
이렇게 슬롯과 범위가 지정된 슬롯에 대해 배웠다.
** 출처: 모든 내용은 Udemy Vue-완벽가이드 강의를 기반으로 작성하였습니다.
'Vue.js' 카테고리의 다른 글
[Udemy Vue 완벽가이드 Section9] 119. 동적 컴포넌트를 활성 상태로 유지하기 (0) | 2023.08.30 |
---|---|
[Udemy Vue 완벽가이드 Section9] 118. 동적 컴포넌트 (component태그) (0) | 2023.08.30 |
[Udemy Vue 완벽가이드 Section9] 116. 슬롯에 대한 추가 정보(fallback 기본컨텐츠, $slots, #default) (0) | 2023.08.30 |
[Udemy Vue 완벽가이드 Section9] 115. 슬롯 스타일 및 컴파일 (0) | 2023.08.30 |
[Udemy Vue 완벽가이드 Section9] 114. 이름이 있는 슬롯(Named Slots) (0) | 2023.08.29 |