컴포넌트에 콘텐츠나 다른 컴포넌트를 또 다른 방식으로 주입시키는 데에 사용하는 방식. 일반적인 부모와 자식 컴포넌트 관계가 아니다. 자신에게 등록된 자식 컴포넌트의 내용을 재정의할 수 있는 방식이다.
마치 React.portal과 비슷한 방식이라 봐도 나쁘지는 않을듯. 완전히 같지는 않지만.
예를 들어 모달의 경우 정형화 된 형태가 있고, 이를 필요한 부분만 바꿔가면서 사용하기 위해 slot을 사용한다. 자식 컴포넌트에 포함되어 있는 slot 요소를 부모 컴포넌트에서 재정의하여 사용할 수 있다.
// SlotModalLayout.vue
// 자식 컴포넌트
<template>
<div class="modal-container">
<header>
**<slot name="header"></slot>**
</header>
<main>
**<slot></slot>**
</main>
<footer>
**<slot name="footer"></slot>**
</footer>
</div>
</template>
// SlotModalUseLayout.vue
<template>
<modal-layout>
<template v-slot:**header**>
<h1>팝업 타이틀</h1>
</template>
<template v-slot:**default**>
<p>팝업 컨텐츠 1</p>
<p>팝업 컨텐츠 2</p>
</template>
<template v-slot:**footer**>
<button>닫기</button>
</template>
</modal-layout>
</template>
<script>
import SlotModalLayout from './SlotModalLayout.vue'
export default {
name: 'SlotModalLayout',
components: {'modal-layout': SlotModalLayout}
}
</script>
<style scoped>
</style>
슬롯을 사용할 레이아웃을 만들 때, 부모 컴포넌트에서 임의로 바꿔치기 할 수 있는 부분을 slot 요소로 만들어 놓는다. 그리고 각 slot 요소에 이름 name
을 지정하여 사용한다.
부모 컴포넌트에서는 v-slot:**name**
으로 자식 컴포넌트에서 지정한 특정 슬롯에 데이터를 넣을 수 있다. 이 때 name이 지정되지 않았다면 default
로 사용해주면 된다.
// Child.vue
<template>
<div>
<h3>Hello, From Child</h3>
</div>
<slot></slot>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
</style>
// App.vue
<template>
<div id="app">Hello World</div>
<Child>
Hello From Slot
</Child> <!-- 자식 컴포넌트 사용 -->
</template>
<script>
import Child from '@/components/Child.vue'
export default {
name: 'App',
components: { // 자식 컴포넌트를 등록하고
Child
},
}
</script>
화면에
Hello World
Hello, From Child
Hello From Slot
이런 순으로 적히게 된다.
범위 컴파일 : 슬롯 사이의 데이터는 부모 자식 컴포넌트 중 누구와 바인딩될까?
// App.vue
<template>
<div id="app">Hello World</div>
<Child>
<button v-on:click="**pressed**">Press</button>
</Child> <!-- 자식 컴포넌트 사용 -->
</template>
<script>
import Child from '@/components/Child.vue'
export default {
name: 'App',
components: {
Child
},
methods: {
pressed() {
alert('hello from **parent**!')
}
}
}
</script>
버튼을 클릭하면 parent의 pressed method가 실행된다! 이는 아무리 자식 컴포넌트의 사이에 있는 데이터라 해도, 부모의 템플릿 안에 있다면 부모 템플릿 범위로 컴파일된다는 의미이다.
Scoped-slot : 자식 컴포넌트 안의 데이터를 부모 컴포넌트로 끄집어 내고 싶을 때