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)