How Vue Components Work

Johnny Simpson - Mar 16 '22 - - Dev Community

Components let us split parts of our site into reusable pieces which we can then place in multiple places. This can be incredibly powerful - and ultimately means reduced workload, as we can reuse code extensively.

You can easily imagine a Vue Component tree that looks a little like the image below. Here, we have a two pages, Home, and About. Within each, we have a reusable component, MyDropdown, which we use twice.

Overview of how Vue Components Work

Since Vue components are so powerful, let's take a look at how they work, and some things you may not know. If you're brand new to Vue, start with our guide on getting started first.

How to create a Component with Vue

Vue components look like any other single file. Let's start by making a basic component. In this example, I've made a file in our components folder called Hello.vue:

<template>
    <div id="hello-main">Hello!</div>
</template>
<script>
export default {
    name: "Hello"
}
</script>
<style scoped>
#hello-main {
    color: green;
    font-weight: 600;
}
</style>
Enter fullscreen mode Exit fullscreen mode

In this basic example, we are creating a component called Hello - and it will produce a div containing the text Hello in green.

Let's now say, I have a page called Home.vue, and want to use this component on that page. We need to import our component, and assign it to our Javascript.

Home.vue:

<template>
    <!-- We can use Hello here, since we mentioned it in our components -->
    <Hello />
    <Hello />
    <Hello />
</template>
<script>
// First, import our component from "Home.vue"
import Hello from '../components/Home.vue';
export default {
    components: {
        // Then add it to our components list - now we can use it in our template tag.
        Home
    }
}
</script>
Enter fullscreen mode Exit fullscreen mode

Since we imported our component from Hello.vue, and added it to our components list, we can now use it freely as the HTML tag <Home /> anywhere on our Home.vue page.

Now we know how to create basic components in Vue, let's look at how to modify and adjust them.

Adding Props to your Components

Just like regular HTML tags, you can add properties to your components. Let's add a property to our Hello.vue component, and use it in our template. Below, we will add the prop "text" to our list of props, with type String.

Now we can use it anywhere in our template. As such, I've replaced the text of our #hello-main div with that prop.

<template>
    <div id="hello-main">{{ text }}</div>
</template>
<script>
export default {
    name: "Hello",
    props: {
        text: String
    }
}
</script>
<style>
#hello-main {
    color: green;
    font-weight: 600;
}
</style>
Enter fullscreen mode Exit fullscreen mode

Now if we want to use this prop in our Home.vue page with a custom prop, we can do this by calling the component along with the prop:

<template>
    <!-- We can use Hello here, since we mentioned it in our components -->
    <Hello text="Hello" />
    <Hello text="Guten Tag" />
    <Hello text="Bonjour" />
</template>
Enter fullscreen mode Exit fullscreen mode

Now, each of these Hello components will have different text - Hello, Guten Tag, and Bonjour, all in green and in bold.

Templating

If you are brand new to Vue, it might help to look at my guide to templating, which will help when building new components in Vue.

Using Slots in your Vue Templates

Sometimes, you will want to put content within your components, similar to how you might put text between two

tags. To do that, we use slots. Let's try adding a slot instead, to our Hello.vue component:

<template>
    <div id="hello-main">
        <slot></slot>
    </div>
</template>
<script>
export default {
    name: "Hello",
}
</script>
<style scoped>
#hello-main {
    color: green;
    font-weight: 600;
}
</style>
Enter fullscreen mode Exit fullscreen mode

Now that we have placed a slot in our component, we can put content within our <Hello /> tag, in our Home.vue file:

<template>
    <!-- We can use Hello here, since we mentioned it in our components -->
    <Hello>Hello</Hello>
    <Hello>Guten Tag</Hello>
    <Hello>Bonjour</Hello>
</template>
Enter fullscreen mode Exit fullscreen mode

Now we have three hello elements, all production green/bold text, saying Hello, Guten Tag, and Bonjour.

Using multiple slots in Vue Components
We can have multiple slots in our Vue component - we simply have to name them. For example, instead of writing just <slot>, we could write <slot name="header"> for a slot named header. Let's update our Hello.vue component to have two slots:

<template>
    <div id="hello-main">
        <h2><slot name="header"></slot></h2>
        <div id="hello-main-content"><slot name="body"></slot></div>
    </div>
</template>
<script>
export default {
    name: "Hello",
}
</script>
<style scoped>
#hello-main h2 {
    color: green;
    font-weight: 600;
}

#hello-main #hello-main-content {
    font-size: 1rem;
    color: rgba(0,0,0,0.8);
}

</style>
Enter fullscreen mode Exit fullscreen mode

Now we have two slots - one called body, and another called header. If we want to use our component in our Home.vue page now, we just have to call out which slot we're defining, like so:

<template>
    <hello>
        <template v-slot:header="">Welcome</template>
        <template v-slot:body="">Welcome to our site</template>
    </hello>
</template>
Enter fullscreen mode Exit fullscreen mode

Now our first slot, header will contain the text "Welcome", while our second, body, will contain the text "Welcome to our site".

Using Kebab Case Components in Vue

When we import a component in Vue, we usually do it with PascalCase. So if we are importing a component called DropDownMenu, we might do this:

<script>
import DropDownMenu from '../components/DropDownMenu.vue';
export default {
    components: {
        DropDownMenu
    }
}
</script>
Enter fullscreen mode Exit fullscreen mode

When we use it in our HTML, however, we can use it either as DropDownMenu, or in kebab case, i.e. drop-down-menu. For example, both of these would refer to DropDownMenu:

<template>
    <DropDownMenu>
    <drop-down-menu>
</template>
Enter fullscreen mode Exit fullscreen mode

Dynamic Components in Vue

Although we sometimes want to specify a component in particular, it can also be useful to programatically set a component dynamically. We can do this in Vue using the <component> tag.

Suppose we have two components - Hello and GoodBye, and we want to change it based on the variable in our data() function. First, we can change how it looks in our template, and use the <component> tag instead:

<template>
    <component :is="selectedComponent"></component>
</template>
Enter fullscreen mode Exit fullscreen mode

The above code will refer to the selectedComponent variable in our data() function, or a prop called selectedComponent. Now, let's look at our Javascript:

<script>
import Hello from '../components/Hello.vue';
import GoodBye from '../components/GoodBye.vue';
export default {
    data() {
        return {
            selectedComponent: "Hello"
        }
    },
    components: {
        Hello,
        GoodBye
    }
}
</script>
Enter fullscreen mode Exit fullscreen mode

selectedComponent is a string, but it refers to one of our components. Since we are referring to our component in our <template> as <component :is="selectedComponent">, if we update our selectedComponent variable to GoodBye, then the component displayed will change.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .