First I'll show you how, then we'll get into why you'd want to hide slots.
Every Vue component has a special $slots
object with all of your slots in it. The default slot has the key default
, and any named slots use their name as the key:
const $slots = {default: <default slot>,icon: <icon slot>,button: <button slot>,};
But this $slots
object only has the slots that are applied to the component, not every slot that is defined.
Take this component that defines several slots, including a couple named ones:
<!-- Slots.vue --><template><div><h2>Here are some slots</h2><slot /><slot name="second" /><slot name="third" /></div></template>
If we only apply one slot to the component, only that slot will show up in our $slots
object:
<template><Slots><template #second>This will be applied to the second slot.</template></Slots></template>
$slots = { second: <vnode> }
We can use this in our components to detect which slots have been applied to the component, for example, by hiding the wrapper element for the slot:
<template><div><h2>A wrapped slot</h2><div v-if="$slots.default" class="styles"><slot /></div></div></template>
Now the wrapper div
that applies the styling will only be rendered if we actually fill that slot with something.
If we don't use the v-if
, we would end up with an empty and unnecessary div
if we didn't have a slot. Depending on what styling that div
has, this could mess up our layout and make things look weird.
There are three main reasons to use a conditional slot:
div
s to add default stylesFor example, when we're adding default styles, we're adding a div
around a slot:
<template><div><h2>This is a pretty great component, amirite?</h2><div class="default-styling"><slot ></div><button @click="$emit('click')">Click me!</button></div></template>
However, if no content is applied to that slot by the parent component, we'll end up with an empty div
rendered to the page:
<div><h2>This is a pretty great component, amirite?</h2><div class="default-styling"><!-- No content in the slot, but this divis still rendered. Oops. --></div><button @click="$emit('click')">Click me!</button></div>
Adding that v-if
on the wrapping div
solves the problem though. No content applied to the slot? No problem:
<div><h2>This is a pretty great component, amirite?</h2><button @click="$emit('click')">Click me!</button></div>