Vue Components
By Flavio Copes
Learn how Vue 3 components work as independent units with their own state and markup, from createApp on a page to local registration and .vue files.
Components are single, independent units of an interface. They can have their own state, markup and style.
How to use components
Vue components can be defined in 4 main ways.
Let’s talk in code.
The first is the root component, the one you pass to createApp():
import { createApp } from 'vue'
createApp({
/* options */
}).mount('#app')
The second is a component registered globally on the app with app.component():
const app = createApp({})
app.component('UserName', {
/* options */
})
app.mount('#app')
The third is local components: components only available inside the parent that registers or imports them (great for encapsulation).
The fourth is .vue files, also called Single File Components.
Let’s dive into the first 3 ways in detail.
Using createApp() with components defined inline in JavaScript is the way to go when Vue is not building the whole page but just a part of it, like a contact form or a shopping cart, and the server renders the rest of the HTML. In that scenario you usually load Vue from a CDN with a <script> tag.
One thing to know: the inline template strings you see below need the Vue build that includes the template compiler. The CDN build (vue.global.js) has it. The default vue import in a Vite project does not, and you get a “runtime compilation is not supported in this build of Vue” warning instead of output. In a Vite project you put templates in .vue files.
In an SPA, where it’s Vue that builds the HTML, Single File Components are the usual choice. You scaffold the project with npm create vue@latest, which sets up Vite. Vue CLI is in maintenance mode.
You mount the app on a DOM element. If you have <div id="app"></div>, mount('#app') renders the root component inside it.
The root component has no tag name of its own, so it’s usually the main container. Other components used in the application get a tag, and you can use that tag multiple times:
<div id="app">
<user-name name="Flavio"></user-name>
</div>
import { createApp } from 'vue'
const UserName = {
props: ['name'],
template: '<p>Hi {{ name }}</p>'
}
createApp({
components: {
UserName
}
}).mount('#app')
What are we doing? We create a root component mounted on #app, and inside it we use the user-name component, which abstracts our greeting to the user.
The component accepts a prop, an attribute we use to pass data down to child components.
The component is registered as UserName and used in the HTML as user-name. The first form is PascalCase, the second is kebab-case, and Vue maps one to the other. Use PascalCase in the JavaScript. In a template written directly in the HTML page, like this one, you must use kebab-case, because the browser lowercases tag names before Vue sees them. Inside .vue files both work.
Local components
Anything you register with app.component() is global for that app.
To keep a component private, define it as an object and list it only where you need it:
const Sidebar = {
template: '<aside>Sidebar</aside>'
}
createApp({
components: {
Sidebar
}
}).mount('#app')
Or import it in a Single File Component:
import Sidebar from './Sidebar.vue'
export default {
components: {
Sidebar
}
}
With <script setup>, an import is enough. Imported components are available in the template automatically:
<script setup>
import Sidebar from './Sidebar.vue'
</script>
<template>
<Sidebar />
</template>
Reusing a component
A child component can be added multiple times. Each separate instance is independent of the others:
<div id="app">
<user-name name="Flavio"></user-name>
<user-name name="Roger"></user-name>
<user-name name="Syd"></user-name>
</div>
import { createApp } from 'vue'
const UserName = {
props: ['name'],
template: '<p>Hi {{ name }}</p>'
}
createApp({
components: { UserName }
}).mount('#app')
The building blocks of a component
So far we’ve seen how a component can accept the props and template properties.
propslists all the properties that we can pass down to a child componenttemplateis where we set up the component template, which defines the output the component generates
A component accepts other properties:
datathe component local statemethods: the component methodscomputed: the computed properties associated with the componentwatch: the component watchers
Those are the Options API. With <script setup> in a .vue file you write the same things as plain variables and functions: ref() for state, a function instead of a methods entry, computed() and watch() imported from vue.
Want me to talk about your product? You can sponsor this site.