Vue 3 is in beta and it’s subject to change.
Vue 3 is the up and coming version of Vue front end framework.
It builds on the popularity and ease of use of Vue 2.
In this article, we’ll look at how to use slots to populate content with Vue 3.
Slots
We can add slots to let us distribute content to the location we want.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<click-button>click me</click-button>
</div>
<script>
const app = Vue.createApp({});
app.component("click-button", {
template: `
<button>
<slot></slot>
</button>`
});
app.mount("#app");
</script>
</body>
</html>
We created the click-button
component with a slot
inside so that we can add our own content between the tags.
It’ll render to the button with ‘click me’ as the content text.
We can also add HTML between the tags.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<click-button><b>click me</b></click-button>
</div>
<script>
const app = Vue.createApp({});
app.component("click-button", {
template: `
<button>
<slot></slot>
</button>`
});
app.mount("#app");
</script>
</body>
</html>
We have the ‘click me’ text in bold since we have the b
tag.
Other components can also be between the tags.
So we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<click-button><hello-world></hello-world></click-button>
</div>
<script>
const app = Vue.createApp({});
app.component("click-button", {
template: `
<button>
<slot></slot>
</button>`
});
app.component("hello-world", {
template: `
<b>click me</b>
`
});
app.mount("#app");
</script>
</body>
</html>
We have the hello-world
component in between the click-button
tags and we’ll see the same result as before.
If a component’s template didn’t contain the slot
element, then any content in between the tags would be discarded.
So if we have:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<click-button>click me</click-button>
</div>
<script>
const app = Vue.createApp({});
app.component("click-button", {
template: `
<button></button>
`
});
app.mount("#app");
</script>
</body>
</html>
Then ‘click me’ wouldn’t be displayed and we have an empty button.
Render Scope
We can access items from the child component from the parent if we have a slot.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<click-button>
delete {{item.name}}
</click-button>
</div>
<script>
const app = Vue.createApp({
data() {
return {
item: {
name: "this"
}
};
}
});
app.component("click-button", {
template: `
<button>
<slot></slot>
</button>
`
});
app.mount("#app");
</script>
</body>
</html>
Then we passed in the item.name
string as the part of the content of the slot in the click-button
component.
This is only for display. item
is still in the parent’s scope.
Fallback Content
Fallback content can be added to a slot.
For example, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<click-button> </click-button>
</div>
<script>
const app = Vue.createApp({
data() {
return {
item: {
name: "this"
}
};
}
});
app.component("click-button", {
template: `
<button>
<slot>submit</slot>
</button>
`
});
app.mount("#app");
</script>
</body>
</html>
to add default content between the slots.
Since we have nothing between the click-button
tags, we’ll see ‘submit’ displayed.
Conclusion
Slots are useful for letting us distribute content within a component.