slot
- 슬롯은 어떤 콘텐츠를 다른 컴포넌트에 전달할 수 있게 됨.
- 활용 사례
: 캐러셀을 만들때 부모 컴포넌트1과 2는 공통된 자식컴포넌트를 사용함.
그러나 그 자식 컴포넌트의 레이아웃은 같지만 컨텐츠 내용만 바꿔 사용할 때 slot 활용할 수 있음. - 리액트에서의 outlet과 비슷하다고 생각됨.
- 공식문서 : 영문 사이트 한글 사이트
✅ 기본사용 - 특정 컨텐츠를 전달 (단일 슬롯 사용)
- Parent1과 Paren2는 Child컴포넌트를 공통으로 사용한다.
그러나 컨텐트 내용은 어떤 부모 컴포넌트 인지에 따라 다르게 나타내야 하는 상황. - Parent에서 아무 컨텐츠도 쓰지 않았다면, 기본 값으로 slot에 정의해둔 컨텐츠인 "default" 가 나온다.
// Parent1.vue - "/home"
<template>
<Child>
<h3>home</h3>
</Child>
</template>
// Parent2.vue - "/detail"
<template>
<Child>
<h3>detail</h3>
</Child>
</template>
// Child.vue
<template>
<div>
<h1>title</h1>
<slot>
<h1>default hello</h1> // home, detail로 변경된다.
</slot>
</div>
</template>
✅ 기본사용 - 컴포턴트 전체 컨텐츠를 전달 (단일 슬롯 사용)
- slot에 들어갈 컨텐츠가 컴포넌트 내용 전체인 경우
: 부모 컴포넌트에 v-slot 자리에 Child 컴포넌트 컨텐츠가 통으로 들어간다.
// Parent.vue
<template>
<Child>
<v-slot></v-slot>
</Child>
</template>
// Child.vue
<template>
<div>
<h1>자식 컴포넌트 전체를 slot으로</h1>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
</div>
</template>
✅ 네임드 슬롯 (여러개 슬롯 사용)
- 부모 컴포넌트에서 아무 컨텐츠도 전달하지 않는다면, Child에 정의된 내용을 기본값으로 보여준다.
- v-slot:header → (축약표현) #header
- default slot은 네임 지정 안해도 된다.
// Parent1.vue
<template>
<div>
<h1>Parent1</h1>
<Child>
<template v-slot:header>
<h1>Header - Parent111</h1>
</template>
<template v-slot:default>
<h1>Default - Parent111</h1>
</template>
<template v-slot:footer>
<h1>Footer - Parent111</h1>
</template>
</Child>
</div>
</template>
// Parent2.vue
<template>
<div>
<h1>Parent2</h1>
<Child>
<template #header>
<h1>Header - Parent222</h1>
</template>
<template #default>
<h1>Default - Parent222</h1>
</template>
<template #footer>
<h1>Footer - Parent222</h1>
</template>
</Child>
</div>
</template>
// Child.vue
<template>
<div class="container">
<slot name="header">
<h1>header - 부모에서 정의 된 컨텐츠가 없으면 기본값으로 이 내용 표출</h1>
</slot>
<!-- default slot은 네임 지정x -->
<slot>
<h1>기본값- 부모에서 정의 된 컨텐츠가 없으면 기본값으로 이 내용 표출</h1>
</slot>
<slot name="footer">
<h1>footer - 부모에서 정의 된 컨텐츠가 없으면 기본값으로 이 내용 표출</h1>
</slot>
</div>
</template>
✅ slot props (자식 slot에서 → 부모로 prop 값 보내기)
자식 컴포넌트에서만 접근할 수 있는 데이터를 부모 컴포넌트로 가져와야 할 경우 slot props 사용
- 예제1. 자식 컴포넌트에서 → 부모 컴포넌트로 , 단순히 prop 넘기기
// Parent1.vue
<template>
<div>
<Child>
<!-- [순서2]부모에서 prop을 받는다. // props = {"someProp":"something"} -->
<template #header="props">
<h1>{{ props.someProp }}</h1>
<p>parent111</p>
</template>
</Child>
</div>
</template>
// Parent2.vue
<template>
<div>
<Child>
<!-- [순서2]부모에서 prop을 받는다. (구조분해할당) -->
<template #header="{ someProp }">
<h1>{{ someProp }}</h1>
<p>parent222</p>
</template>
</Child>
</div>
</template>
// Child.vue
<template>
<div class="container">
<!-- [순서1] 자식 컴포넌트 slot에서 prop을 넘겨준다. -->
<slot name="header" :someProp="some"> </slot>
<p>slot에서 prop을 넘겨준다.</p>
</div>
</template>
<script>
export default {
name: "ChildView",
data() {
return {
some: "something",
};
},
};
</script>
- 예제2. 자식의 slot내용에서 → 부모로 “이벤트 객체”를 prop으로 넘기기
// Parent.vue
<template>
<div>
<Child>
<!-- [순서2]부모에서 prop을 받는다.
축약임. 원랜 {on : {mouseenter: mouseenter(), mouseleave :mouseleave () }}-->
<template #header="{ on }">
<button v-on="on">버튼</button>
</template>
</Child>
</div>
</template>
// Child.vue
<template>
<div class="container">
<!-- [순서1] 자식 컴포넌트 slot에서 prop을 넘겨준다. -->
<slot name="header" :on="{ mouseenter, mouseleave }"> </slot>
<p>slot에서 prop을 넘겨준다.</p>
</div>
</template>
<script>
export default {
name: "ChildView",
methods: {
mouseenter() {
console.log("mouseenter!!");
},
mouseleave() {
console.log("mouseleave~");
},
},
};
</script>
※ 이벤트 바인딩 v-on
<h1 v-on:click="dothisFn"> </h1>
<h1 @click="dothisFn"> </h1> // 축약
// 여러 이벤트 타입을 등록할 떄
<h1 v-on="{click: dothisFn, mousedown: mouseFn}"> </h1>
- 예제3 툴팁 만들기 (이벤트객체 관련)
: 토글 여부를 자식요소의 데이터로 관리하고 있음
그 데이터를 컨트롤 하는 이벤트 핸들러를 slot prop으로 부모로 전달,
이후 부모 컴포넌트에서 이벤트 발생되고 > 자식 컴포넌트의 데이터가 바뀜에 따라 토글 내용이 slot으로 들어오고 빠지게됨.
// Parent.vue
<template>
<div>
<h1>Parent</h1>
<Child>
<!-- [순서2] 자식으로 부터 prop을 받아서 버튼에 걸어줌, 부모에서 자식 데이터 제어
축약 {on : { click: showDialog }} -->
<template v-slot:activator="{ on }">
<v-btn v-on="on">show</v-btn>
</template>
<template v-slot:showContent>
<h3>토글 내용</h3>
</template>
</Child>
</div>
</template>
// Child.vue
<template>
<div class="container">
<h1>Child</h1>
<!-- [순서1]부모 컴포넌트로, click이벤트시 자식 컴포넌트의 data 바꾸는 함수를 prop으로 보내줌 -->
<slot name="activator" :on="{ click: showDialog }"> </slot>
<!-- [순서3] show가 true일 경우에만 보여지는 slot -->
<slot name="showContent" v-if="show"> </slot>
</div>
</template>
<script>
export default {
data() {
return {
show: false,
};
},
methods: {
showDialog() {
this.show = !this.show;
},
},
};
</script>
'프론트엔드 > vue' 카테고리의 다른 글
v-model 에 대해 (0) | 2023.05.12 |
---|---|
v-slot (0) | 2023.05.10 |
vue best practice (0) | 2023.05.08 |
data 초기값을 computed로 할 수 없는 이유 (0) | 2023.04.14 |
[vue router] a태그와 router-link의 차이 (0) | 2023.03.26 |