Slot
- slot은 컨텐츠 배포 outlet 역할을 하는 커스템 Vue Eelement
사용방법
App.vue: props 버전
<template>
<main>
<BaseButton text="Cancel" />
<BaseButton text="Submit" right-icon="right-arrow" />
</main>
</template>
App.vue: slot 버전
<template>
<main>
<BaseButton>Cancel</BaseButton>
<BaseButton>Submit <span class="icon right-arrow"></span></BaseButton>
</main>
</template>
Slot에 default값 적용
BaseButton.vue
<template>
<button class="button">
<slot>Submit</slot>
</button>
</template>
- Slot에 값을 제공하면 default 컨텐츠를 override(재정의) 한다.
<!-- BaseButton with no custom content -->
<BaseButton></BaseButton>
<!-- Rendered BaseButton with no custom content -->
<button class="button">Submit</button>
<!-- BaseButton with custom content -->
<BaseButton>Cancel</BaseButton>
<!-- Rendered BaseButton with custom content -->
<button class="button">Cancel</button>
Named Slots
- Slot이 서로 고유하도록 설정하는 방법
- Slot에는 사용자 지정 식별자로 지정할 수 있는 named prop이 있다.
<template v-slot:header></template>
<!--위 코드는 아래와 같다.-->
<template #header></template>
Scoped Slots
- 자식 props를 부모에서 사용 하고자 할 때 사용
- 하위 Component가 상위 Component가 필요로하는 데이터를 제어하고자 할 때 사용
- slot의 template 블록에 데이터를 노출할 수 있도록 하는 기술
- Named Slot을 사용할 수도 있다.
- 숫자는 상관없지만, 문자의 경우 script에서 변수를 선언해서 담아준 후 return시켜 사용해야 한다.
사용방법1 (& Named Slots)
App.vue
<script>
import MyComponent from './MyComponent.vue'
export default {
components: {
MyComponent
}
}
</script>
<template>
<MyComponent v-slot="test">
{{ test.text }} {{ test.count }} {{test}}
</MyComponent>
</template>
<!--slot에 있는 prop을 직접 명시해서 다음과 같이 사용할 수도 있다.-->
<template>
<MyComponent v-slot="{text, count}">
{{ text }} {{ count }}
</MyComponent>
</template>
MyComponent.vue
<script>
export default {
data() {
return {
greetingMessage: 'hello'
}
}
}
</script>
<template>
<div>
<slot :text="greetingMessage" :count="1"></slot>
</div>
</template>
사용방법2 (FancyList)
App.vue
<script>
import FancyList from './FancyList.vue'
export default {
components: {
FancyList
}
}
</script>
<template>
<FancyList api-url="url" :per-page="10">
<template #item="{ body, username, likes }">
<div class="item">
<p>{{ body }}</p>
<p class="meta">by {{ username }} | {{ likes }} likes</p>
</div>
</template>
</FancyList>
</template>
<style scoped>
.meta {
font-size: 0.8em;
color: #42b883;
}
</style>
FancyList.vue
<script>
export default {
props: ['api-url', 'per-page'],
data() {
return {
items: []
}
},
mounted() {
// mock remote data fetching
setTimeout(() => {
this.items = [
{ body: 'Scoped Slots Guide', username: 'Evan You', likes: 20 },
{ body: 'Vue Tutorial', username: 'Natalia Tepluhina', likes: 10 }
]
}, 1000)
}
}
</script>
<template>
<ul>
<li v-if="!items.length">
Loading...
</li>
<li v-for="item in items">
<slot name="item" v-bind="item"/>
</li>
</ul>
</template>
<style scoped>
ul {
list-style-type: none;
padding: 5px;
background: linear-gradient(315deg, #42d392 25%, #647eff);
}
li {
padding: 5px 20px;
margin: 10px;
background: #fff;
}
</style>
사용방법3 (Renderless Components)
App.vue
<script>
import MouseTracker from './MouseTracker.vue'
export default {
components: {
MouseTracker
}
}
</script>
<template>
<MouseTracker v-slot="{ x, y }">
Mouse is at: {{ x }}, {{ y }}
</MouseTracker>
</template>
MouseTracker.vue
<script>
export default {
data() {
return {
x: 0,
y: 0
}
},
methods: {
update(e) {
this.x = e.pageX
this.y = e.pageY
}
},
mounted() {
window.addEventListener('mousemove', this.update)
},
unmounted() {
window.removeEventListener('mousemove', this.update)
}
}
</script>
<template>
<slot :x="x" :y="y"/>
</template>
728x90
반응형
'FrameWorks > Vue' 카테고리의 다른 글
VueRouter의 Router Instance 파헤치기 (0) | 2024.06.21 |
---|---|
Vue의 ObjectBinding (0) | 2024.06.12 |
Vue의 Props 파헤치기 (0) | 2024.06.12 |
Vue의 watchEffect 와 watch 파헤치기 (0) | 2024.06.12 |
Vue의 ModelValue 파헤치기 (0) | 2024.06.12 |
댓글