Legacy Content Notice: This post demonstrates Vue 2 global component registration from 2016. For modern Vue 3 development with Single File Components and Composition API, see our Modern Vue.js Development Guide.
In this tutorial we're going to learn how we can create reuseable templates in VueJS by creating Vue components. For this example we're going to re-visit the todo list loop from a previous tutorial. To recap to create a list item for the todo we needed a HTML template of this
<div id="app">
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>
</div>
Now we're going to swap out the list item element for a reuseable todo-item component that we can reuse anywhere in our app. To start with we need to change the HTML to replace the list item with the new todo-item component, while keeping the for loop.
<div id="app">
<ul>
<todo-item v-for="todo in todos"></todo-item>
</ul>
</div>
The Vue object is going to be exactly the same as the previous tutorial of having an array of objects used in the todo.
var app = new Vue({
el: '#app',
data: {
todos: [
{ task: 'Learn JavaScript'},
{ task: 'Learn VueJS'},
{ task: 'Build awesome stuff'}
]
}
})
With the data setup and the HTML setup with the new component we need to create the component object.
Vue.component('todo-item', {
template: '<li>{{ todo.task }}</li>'
})
When you view this in the browser you'll now see it display the todo items on the page but they will not be populated with the text from the todo. This is because each VueJS component is built within it's own scope so we will need to pass the todo object into the component. To pass the value into the component we need to use props which allows the parent object to pass data into the child objects. Our todo-item now changes to this.
Vue.component('todo-item', {
props: ['todo'],
template: '<li>{{ todo.task }}</li>'
})
This gives us a todo object in the child component where we can access the task property. To pass these todos into the child component from the parent we need to bind to the current todo object by using the v-bind directive.
<div id="app">
<ul>
<todo-item v-for="todo in todos" v-bind:todo="todo"></todo-item>
</ul>
</div>
Now when you refresh the browser you'll see the list of todo tasks.
Modern Vue 3 Single File Component Approach
Here's how to create the same component structure using modern Vue 3:
Parent Component (TodoApp.vue)
<template>
<div class="todo-app">
<ul class="todo-list">
<TodoItem v-for="todo in todos" :key="todo.id" :todo="todo" />
</ul>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import TodoItem from "./components/TodoItem.vue";
interface Todo {
id: number;
task: string;
completed: boolean;
}
const todos = ref<Todo[]>([
{ id: 1, task: "Learn JavaScript", completed: false },
{ id: 2, task: "Learn Vue 3", completed: false },
{ id: 3, task: "Build awesome stuff", completed: false },
]);
</script>
<style scoped>
.todo-list {
list-style: none;
padding: 0;
}
</style>
Child Component (TodoItem.vue)
<template>
<li class="todo-item" :class="{ completed: todo.completed }">
<input
type="checkbox"
v-model="todo.completed"
@change="$emit('toggle', todo.id)"
/>
<span class="task-text">{{ todo.task }}</span>
</li>
</template>
<script setup lang="ts">
interface Todo {
id: number;
task: string;
completed: boolean;
}
// Define props with TypeScript support
defineProps<{
todo: Todo;
}>();
// Define emitted events
defineEmits<{
toggle: [id: number];
}>();
</script>
<style scoped>
.todo-item {
padding: 0.5rem;
border-bottom: 1px solid #eee;
}
.completed .task-text {
text-decoration: line-through;
opacity: 0.6;
}
</style>
Key Modern Improvements:
- TypeScript support with automatic type checking
- Single File Components with scoped styling
- Composition API for better logic reuse
- Proper key attributes for list rendering performance
- Event emission for parent-child communication
- Better developer experience with tooling support
Related Resources
- Modern Vue.js Development Guide - Complete guide to Vue 3 components and patterns
- Vue 3 Component Communication - Modern props and events
- Single File Components - Official Vue 3 SFC documentation
This post demonstrates Vue 2 global component patterns and is preserved for historical reference. Modern Vue development uses Single File Components with the Composition API for better maintainability and type safety.