First time I met using slots in Vue.js
I wanted to figure out how it works, because I could not develop tests without a deep understanding of this concept.
Let's see how it works
components/MyComponent.vue
<script setup>
const greetingMessage = 'hello';
const someNumber = 123;
</script>
<template>
<div>
<slot name="header" :text="greetingMessage" :count="someNumber"></slot>
<slot :text="greetingMessage" :count="someNumber"></slot>
<slot name="footer" :text="greetingMessage" :count="someNumber"></slot>
</div>
</template>
App.vue
<script setup lang="ts">
import MyComponent from './components/MyComponent.vue';
</script>
<template>
<MyComponent>
<template #header="headerProps">
<p>HEADER: {{ headerProps }}</p>
</template>
<template #default="defaultProps">
<p>DEFAULT: {{ defaultProps }}</p>
</template>
<template #footer="{ text, count }">
<p>FOOTER: {{ text }} = {{ count }}</p>
</template>
</MyComponent>
</template>
Slots inside Components
- By default a slot works as a
{ children }
parameter in React components. It provides a way to take a content of a Component (<MyComponent>CONTENT HERE</MyComponent>
) and place it inside internals of the component. - In a component Slot reserves a place where a content will be placed, if the content comes from the parent level.
- A component may have multiple slots inside
- Slot without a name, by default has name
default
Slots outside Components
- WOW! From the inside of the component slots may pass data on the level of parent.
<slot name="header" :text="hello">
passes the text
variable to template
(to the upper level)
<template #header="headerProps">
now inside <template #header>
you can use
{{ headerProps.text }}
- WOW! Ordering of slots inside a component defines an order outside, and affects on ordering of templates.
Even if here we have an order: header
, default
, footer
<MyComponent>
<template #header="headerProps">
<p>HEADER: {{ headerProps }}</p>
</template>
<template #default="defaultProps">
<p>DEFAULT: {{ defaultProps }}</p>
</template>
<template #footer="{ text, count }">
<p>FOOTER: {{ text }} = {{ count }}</p>
</template>
</MyComponent>
but if we define the order of slots like that footer
, header
, default
:
<slot name="footer" :text="greetingMessage" :count="someNumber"></slot>
<slot name="header" :text="greetingMessage" :count="someNumber"></slot>
<slot :text="greetingMessage" :count="someNumber"></slot>
Then it will produce the result
FOOTER: hello = 123
HEADER: { "text": "hello", "count": 123 }
DEFAULT: { "text": "hello", "count": 123 }
It was pretty unexpected to me.
Happy Coding!
Top comments (0)