Vue.js : Slots.

Sean Norton
4 min readApr 15, 2019

Want to nest your components inside of each other from the parent level? Curious how you do that thing React does with props.children? Slots might be what you’re looking for.

Getting Started

I’m going to start with the basic setup that Vue.js gives us when using the command line, but I’ll delete some things we don’t really need in the templates first. So now we’re left with a HelloWorld component that renders a message property passed from App.vue.

// App.vue<template>
<div id="app">
<HelloWorld msg="Welcome to your Vue.js App">
</div>
</template>
// HelloWorld.vue<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>

Basic Use

So let’s say that instead of passing in a property of ‘msg’ we just want to write our message between two HelloWorld element tags and then have that render on the page. What we’ll do is this:

// AppV.vue<template>
<div id="app">
<HelloWorld>
<h1>Welcome to your Vue.js App</h1>
</HelloWorld>

</div>
</template>
// HelloWorld.vue<template>
<div class="hello">
<slot> </slot>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
p̶r̶o̶p̶s̶:̶ ̶{̶m̶s̶g̶:̶ ̶s̶t̶r̶i̶n̶g̶}̶,̶
}
</script>

As you can see in the example above, we moved our message <h1> into the App.vue and placed it between a pair of HelloWorld tags. This means we can get rid of the props in our HelloWorld component since we do not pass it any props. And now our message gets rendered using <slot/> instead.

Custom Button

The example above doesn’t really make too much sense to use. you might as well use the props and write less code in the parent. but this logic could be applied to lots of things. Let’s take a button for example:

// CustomButton.vue
<template>
<button> <slot></slot> </button>
</template>
// App.vue
<template>
<div id="app">
<HelloWorld> <h1> Hello World</h1> </HelloWorld>
<CustomButton type="submit"> SAVE! </CustomButton>
</div>
</template>

In this example we get to write our custom button out, much like a regular html button, passing the text value between our button tags. and here I’ve also passed a property of type since we might want to use that if the button was functional.

But Wait There’s More…

Slots can have names and render other components, not just lame-o text.

Slot Names

Let’s say you have a Modal that you want to display a header, body and footer. This might change each time you use the Modal so you don’t want to hardcode the look/values into the Modal itself.

// Modal.vue
<template>
<div class="modal">
<slot name="header"> </slot>
<slot> </slot>
<slot name="footer"> </slot>
</div>
</template>

In this example we’ve set three slots and gave them names that way we can later make sure that our data gets rendered where we want it.

If you don’t give a slot a name, it becomes the default slot.

To then make sure we render properly into the Modal, on the parent component we’ll do this:

// App.vue
<template>
<Modal>
<template v-slot:header>
<h1>Modal Header Text</h1>
</template>
<h2>Modal Body</h2>
<p>Some more text to render</p>
<template v-slot:footer>
<p>Footer Text</p>
<button>Close</button>
</template>
</Modal>
</template>

The important thing to note here is that when you give a slot a name, on your parent component you’ll need to use <template v-slot:name> slot stuff </template>

Slots holding Components

This is where things get good If you ask me, let’s say that we created a custom body component that renders like a map and some data with it. We can make that render into our Modal’s slot real easy.

// App.vue
<template>
<Modal>
<template v-slot:header>...</template>
<ModalMapComp
place="placeProperty"
mapInfo="map"
/>
<template v-slot:footer>...</template>
</Modal>
</template>

Here I’ve just passed in a ModalMap Component, this component takes in a place and mapInfo property. I don’t want every Modal I have to use a Map, and I don’t care for having the Modal take in a bunch of information just to figure out if it needs to render a map or profile or something else.

That’s why I would choose to use a slot here let the parent decide what’s loaded and just use the Modal as ‘dumb’ floating box like it should be.

I write these blog posts as a way to help better understand things myself and then hopefully help out someone else. That being said: Let me know how you’d use this, or if I said something dumb, I’m here to learn. :)

Slot Docs on Vue.js

--

--

Sean Norton

Software Developer, focusing on Javascript and other front end technologies.