Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.
In this article, we’ll look at distributing components with slots and dynamic components.
Distributing Components with Slots
We can pass content in components by putting text between the opening and closing tags.
To do this, we can add a slot to our component with the slot
element.
For example, we can use it as follows:
src/index.js
:
Vue.component("error-box", {
template: `
<div v-bind:style="{color: 'red'}">
<slot></slot>
</div>
`
});
new Vue({
el: "#app",
data: {
text: ""
}
});
index.html
:
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head> <body>
<div id="app">
<error-box>Error</error-box>
</div> <script src="src/index.js"></script>
</body>
</html>
The text Error
that we put between the error-box
tags replace the slot
tag, so we get the word ‘Error’ in red displayed.
Dynamic Components
We can switch dynamically between components by using v-bind:is
.
The value of v-bind:is
can contain either the name of a registered component or a component’s options object.
For example, we can use it as follows:
src/index.js
:
Vue.component("tab-foo", {
template: "<div>Foo</div>"
});
Vue.component("tab-bar", {
template: "<div>Bar</div>"
});
Vue.component("tab-baz", {
template: "<div>Baz</div>"
});
new Vue({
el: "#app",
data: {
currentTab: "foo"
},
computed: {
currentTabComponent() {
return `tab-${this.currentTab.toLowerCase()}`;
}
}
});
In the code above, we created 3 components, and in the root Vue instance, we have the currentTab
field so that we can add buttons to change the content in the HTML template.
The currentTabComponent
will be updated as this.currentTab
changes, which we’ll set the value of with buttons in the template.
index.html
:
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head> <body>
<div id="app">
<button @click='currentTab = "foo"'>Foo</button>
<button @click='currentTab = "bar"'>Bar</button>
<button @click='currentTab = "baz"'>Baz</button>
<component v-bind:is="currentTabComponent"></component>
</div> <script src="src/index.js"></script>
</body>
</html>
In the template above, we have 3 buttons with click event handlers to set the currentTab
value, which will also set the currentTabComponent
property as currentTab
changes.
Since we passed currentTabComponent
to v-bind:is
, the component
element will replace the component with the name set in currentTabComponent
.
So when we click the Foo button we get Foo, when we click the Bar button we get Bar, and when we click the Baz button we get Baz.
We can pass in an object to v-bind:is
as follows:
src/index.js
:
new Vue({
el: "#app",
data: {
tabBar: {
template: "<div>Bar</div>"
}
}
});
index.html
:
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head> <body>
<div id="app">
<component v-bind:is="tabBar"></component>
</div> <script src="src/index.js"></script>
</body>
</html>
We passed in the tabBar
object as the value of v-bind:is
directive.
DOM Template Parsing Issues
Some HTML elements have restrictions on what can be inside them. For example, ul
must have li
elements inside them.
We can nest whatever element we want with the is
attribute.
For example, we can use it as follows:
src/index.js
:
Vue.component("list-item", {
template: "<div>Foo</div>"
});
new Vue({
el: "#app"
});
index.html
:
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head> <body>
<div id="app">
<ul>
<li is="list-item"></li>
</ul>
</div> <script src="src/index.js"></script>
</body>
</html>
The code above sets the list-item
component as the component inside the li
element.
This limitation doesn’t apply if we’re using string templates from one of the following sources:
- String templates (e.g.
template: '...'
) - Single-file (
.vue
) components <script type="text/x-template">
Conclusion
We can get the content of items in between the opening and closing tags of our component with the slot
element.
The component
element let us change the component dynamically by passing in a string name for the component.
We can pass an object or a string with the component name to v-bind:is
.