Vue.js: notes on Slots
Vue slots allow us to create generic components, by passing template content (custom markup) to child components.
Let’s say we have a MyButton component which we’d like to make generic. We can
set a slot inside its template:
<button> <slot></slot></button>We can then pass custom content to MyButton:
<MyButton>Submit</MyButton>The HTML node Submit replaces the tag <slot></slot> when the component gets
rendered.
Optionally, we can specify some fallback content, to be rendered when the parent does not provide content for a slot:
<button> <slot>Click me</slot></button>We’re not limited to text, we can also pass any valid template content:
<MyButton> <strong>S</strong>ubmit</MyButton>Since we didn’t explicitly name the slot above, it will implicitly become the
default slot, named default. The following achieves the same result as the
above:
<MyButton> <template v-slot:default> <strong>S</strong>ubmit </template></MyButton>Instead of v-slot:, we can use the shorthand #, as in <template #default>.
Named slots start to become useful when we want our component to provide more than one slot:
<button> <slot name="emoji"></slot> <slot>Click me</slot></button><MyButton> <template v-slot:emoji>👍</template> <template v-slot:default> <strong>S</strong>ubmit </template></MyButton>Sometimes we may have some state inside our child component that we’d need the parent to be aware of (to render the content of a slot). We can use scoped slots to achieve that:
<button @mouseenter="hover = true" @mouseleave="hover = false"> <slot name="emoji" :hover="hover"></slot> <slot>Submit</slot></button>{% raw %}<MyButton> <template #emoji="{ hover }">{{ hover ? '👍' : '👎' }}</template></MyButton>{% endraw %}