Introduction
When developing a large application, it is always a good idea to break it down into smaller components to make the code easier to read, structure, and maintain. Most Vue beginners understand what components are at least conceptually, but they might not understand what they can and cannot do fully.
In this guide, we'll take a look at what a component in Vue is, how it works, how to pass data and events through them and lots more.
What is a Vue Component?
Components are reusable instances of Vue elements that include templates, styles, and JavaScript elements. Each component is "its own thing", similar to how each HTML element is "its own thing", and both Vue components and HTML elements allow us to use them as building blocks for web pages.
You can think of Vue components as JavaScript-imbued HTML elements, that you can define and manipulate yourself.
A typical Vue application is made up of numerous components that can be reused as many times as needed.
For example, a usual website has sections that appear on all pages - navbar, header, footer, and so on. Therefore, it's considered a good practice to make each of them a separate component. That way, we are creating well-structured, readable, reusable, and easily maintainable code:
How to Create a Vue Component
There are two basic ways to create a Vue component, depending on how our project was created - with or without a build setup. In the first case, every component is stored in a separate file. In the second case, there can be multiple components in a single file.
Note: Explaining what is a build setup and how to perform it is far beyond the scope of this guide. If you want to learn more about Vue basics, the good place to start is the "Quick Start" article from the official Vue documentation.
Create Vue Components With a Build Setup
Most projects are created using the build setup, which enables us to create Single-File Components (SFCs) - dedicated component files with the .vue
extension. This allows us to encapsulate a Vue component's template, logic, and styling in a single file:
<!-- Vue-specific JavaScript -->
<script>
export default {
data() {
return {
title: 'Hello World!'
}
}
}
</script>
<!-- HTML Template -->
<template>
<div>
<p class="title">{{ title }}</p>
</div>
</template>
<!-- CSS Styling -->
<style>
.title {
color: red;
}
</style>
Note: To avoid conflicts with existing and future HTML elements, it's always best to use multi-word names rather than single-word names when naming our components. This does not apply to built-in components such as the root component (App
, Transition
, and so on).
Create Vue Components Without a Build Setup
If you, for whatever reason, cannot use a package manager such as npm
to install Vue on your machine, you can still use Vue in your app. An alternative to building Vue using npm
is to install Vue via a CDN (Content Delivery Network) directly in your app. Let's just quickly go over this way of creating a Vue component.
Installing Vue without build will enable us to use Vue-specific functionalities as we do with plain JavaScript. The syntax is somewhat similar to what we've seen in the usual SFCs:
export default {
data() {
return {
title: 'Hello World!'
}
},
template: `
<div>
<p class="title">{{ title }}</p>.
</div>`
}
In this guide, we will be using the SFC syntax, as that is the most commonly used method of creating components.
How to Register Components in Vue
So far, we've seen how to create components in Vue. The next step will be to use these components within another component (parent-child hierarchy).
To do so, we must first register components we want to use. This registration entails importing and then registering components. There are two options for doing so - global and local registration.
Vue Components - Global Registration
Globally registered components, as the name implies, are available globally, which means they can be used in any component of our application without us having to import them again. This is accomplished by registering a component using the app.component()
method:
import ChildComponent from './App.vue'
app.component('ChildComponent', ChildComponent)
In a situation where we have many components, we can chain them this way:
app
.component('ChildComponent', ChildComponent)
.component('ProfileComponent', ProfileComponent)
After we've registered our components, we can use them in the template of any component within this application using the following syntax:
<ChildComponent/>
<ProfileComponent/>
Vue Components - Local Registration
We will use local registration in most cases because it allows us to scope the availability of our registered components. Importing these components and then adding them to the components
option accomplishes this:
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
}
}
</script>
<template>
<ChildComponent />
</template>
When naming components, use CamelCase to make it clear that this is a Vue component rather than a native HTML element in templates. This also makes it easier to import and register components in JavaScript.
Note: For referencing our registered component within the template, we typically use CamelCase or kebab-case tags - <MyComponent />
or <my-component />
, respectively.
How to Pass Data Through Vue Components
One of the benefits of creating components is the ability to reuse code by making it modular.
Assume we are creating a user's profile component that needs to receive each student's data from the profile page; in this case, we must pass this data down from the profile component (parent component) to the user-profile component (child component), and we will use props.
Props
Props are custom attributes we can register on a component, so we can pass data from the parent component to the child component using the props
option within the script tag:
<script>
export default {
props: {
title: String,
}
}
</script>
<template>
<h4>{{ title }}</h4>
</template>
Note: You can learn more about props and how to pass different types of data from the parent component to the child component in "Guide to Vue Props".
Slots
Vue slots are reserved spaces that allow us to pass any type of content from one component to another. This gives more centralized control than props because, unlike props, the parent component controls the content inside the child component. For example, we could make the following button:
<!-- my-button.vue -->
<template>
<button class="btn btn-style">
<slot>Click Me</slot>
</button>
</template>
Then we can use this component anywhere we want and give it the content we desire. Failure to give it a content means it will make use of the default value we gave it (Click Me):
<!-- my-form.vue -->
<template>
<my-button>
Submit Form <img src="/img/icons/arrow-icon.jpg">
</my-button>
</template>
How to Emit Events from Vue Components
We learned that props are used to send data from the parent component down to the child component. But we might wonder if there was a way to send something from the child component to the parent component. And the answer is yes, events can be sent from the child component to the parent component too.
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
Assume we have a parent component (App.vue
) that contains a single child component (MyBlogPost.vue
). Furthermore, the child component contains a button which is supposed to change the title.
Assume we want to change the title of our page when a button is clicked, so that a function is triggered:
<!-- App.vue -->
<script>
import MyBlogPost from './BlogPost.vue'
export default {
components: {
MyBlogPost
},
data() {
return {
title: "Hello World"
}
},
methods:{
changeText: function(){
this.title = "New Title"
}
}
}
</script>
<template>
<div>
<MyBlogPost :title="title" @change-text=changeText></MyBlogPost>
</div>
</template>
And the child component will look like this:
<!-- MyBlogPost.vue -->
<script>
export default {
props: ['title'],
emits: ['change-text']
}
</script>
<template>
<div class="blog-post">
<h4>{{ title }}</h4>
<button @click="$emit('change-text')">Change Title</button>
</div>
</template>
Conclusion
In this guide, we've learned how to work with components in Vue, which is essential for anyone using Vue. We also learned how to send and receive data, as well as how to emit events.