What Is a Vue Component?
Components are reusable Vue instances with a name. They allow you to build modular pieces of UI that can be composed together to form complete applications. Think of components as custom HTML elements that encapsulate specific functionality and appearance.
Single File Components (SFCs)
Vue Single File Components (SFCs) are special files with the .vue extension that combine template (HTML), logic (JavaScript/TypeScript), and styling (CSS) in a single file:
<template>: Defines the component's HTML structure using Vue's template syntax<script>: Contains the component's logic, including data, methods, and lifecycle hooks<style>: Holds CSS/SCSS styles, with optionalscopedattribute for component-scoped styling
Component Benefits
- Reusability: Write once, use anywhere across your application
- Maintainability: Self-contained units are easier to debug and modify
- Organization: Break complex UIs into manageable, logical pieces
- Testability: Components can be unit tested in isolation
Components are the foundation of modern web development, enabling teams to build scalable applications with clean, maintainable code. Understanding how components work is essential for any developer working with HTML and CSS or JavaScript frameworks like React.
Creating Your First Component
Let's create a simple TodoItem component that displays a task with a checkbox.
The Component File
<script setup lang="ts">
import { ref } from 'vue'
// Component logic here
</script>
<template>
<div class="todo-item">
<input type="checkbox" id="todo-checkbox" />
<label for="todo-checkbox">My Todo Item</label>
</div>
</template>
<style scoped>
.todo-item {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem;
}
</style>
Understanding the Structure
- The
<script setup>syntax provides a cleaner, more concise way to write Composition API components - The
<template>defines what the component renders to the DOM - The
scopedattribute on<style>ensures CSS only applies to this component
This approach aligns with Vue 3 best practices for component-based architecture, where developers create modular, reusable pieces that work seamlessly together.
Just as local variables help organize code logic within functions, components organize UI elements into self-contained units.
Making Components Dynamic with Props
Props are how components receive data from their parents. They make components dynamic and reusable by allowing different data to be passed in.
Defining Props
Vue 3 provides two ways to define props:
<script setup lang="ts">
// Object syntax with type validation (recommended)
defineProps({
label: {
type: String,
required: true
},
done: {
type: Boolean,
default: false
}
})
</script>
Or using TypeScript syntax:
<script setup lang="ts">
defineProps<{
label: string
done?: boolean
}>()
</script>
Using Props in Templates
Once props are defined, use them in your template:
<template>
<div class="todo-item">
<input
type="checkbox"
:id="`todo-${label}`"
:checked="done"
/>
<label :for="`todo-${label}`">{{ label }}</label>
</div>
</template>
The {{ }} syntax (mustache interpolation) displays the value of the label prop. Vue reactivity ensures the display updates when prop values change.
Prop Validation
Vue provides built-in prop validation:
<script setup lang="ts">
defineProps({
// Required string
title: { type: String, required: true },
// Number with default
count: { type: Number, default: 0 },
// Boolean flag
enabled: { type: Boolean, default: false },
// Array with factory function
items: { type: Array, default: () => [] },
// Custom validator function
status: {
type: String,
validator: (value) => ['active', 'pending', 'done'].includes(value)
}
})
</script>
Building components with strong prop contracts ensures maintainable codebases and predictable behavior across your application.
Using Components in Parent Components
Importing and Registering Components
To use TodoItem in a parent component like App.vue:
<script setup lang="ts">
import { ref } from 'vue'
import TodoItem from './components/TodoItem.vue'
// Component is now available in template
</script>
<template>
<div id="app">
<h1>My Todo List</h1>
<ul>
<li>
<TodoItem label="Learn Vue components" :done="true" />
</li>
<li>
<TodoItem label="Build a project" :done="false" />
</li>
</ul>
</div>
</template>
Component Naming Conventions
- Component file names: PascalCase (e.g.,
TodoItem.vue,UserProfile.vue) - Template usage: kebab-case (e.g.,
<todo-item>,<user-profile>)
This follows web standards and ensures compatibility across different template contexts.
Proper component composition is essential for maintainable codebases and scalable application architecture. Just as Angular styling helps organize visual presentation, proper component organization keeps your application structure clean.
Vue 3 Composition API and script setup
Why Composition API?
The Composition API, especially with <script setup>, is the recommended approach for Vue 3:
- Better TypeScript support: Native typing without additional boilerplate
- Logic reuse: Extract and share composable functions across components
- Organized code: Group related logic by feature, not by option type
- Smaller output: More efficient runtime with less boilerplate
Reactive Data with ref and computed
<script setup lang="ts">
import { ref, computed } from 'vue'
// Reactive state
const newItem = ref('')
const items = ref([
{ id: 1, label: 'Learn Vue', done: true },
{ id: 2, label: 'Build something', done: false }
])
// Computed property
const completedCount = computed(() =>
items.value.filter(item => item.done).length
)
// Methods
function addItem() {
if (newItem.value.trim()) {
items.value.push({
id: Date.now(),
label: newItem.value,
done: false
})
newItem.value = ''
}
}
</script>
The Composition API represents the modern way to build Vue applications with improved developer experience and better long-term maintainability. This pattern aligns with how AI automation systems organize complex workflows into composable, reusable units that can be orchestrated together.
Best Practices for Vue Components
Component Design Principles
- Single Responsibility: Each component should do one thing well
- Props over Internal State: Make components configurable through props rather than internal state when data comes from parent
- Meaningful Names: Use descriptive, PascalCase names (UserProfile, TodoList, etc.)
- Avoid Deep Nesting: Keep component hierarchy shallow for better performance and maintainability
Performance Considerations
- Lazy Loading Components: Use dynamic imports for components that aren't immediately needed
- v-memo: Cache template subtrees for performance optimization
- Keep Components Light: Extract complex logic into composables or utilities
Style Organization
<style scoped>
/* Component-specific styles */
.todo-item {
/* Styles here only affect this component */
}
</style>
Use the scoped attribute to prevent style leakage, or remove it for global styles that should apply everywhere.
Building components with these practices ensures your Vue.js applications remain performant and scalable as they grow. Similar principles apply when fixing JavaScript performance issues in larger applications.
Single File Components
Organize template, script, and style in one .vue file
Props System
Pass data to components with type validation and defaults
Composition API
Modern Vue 3 approach with better TypeScript support
Scoped Styles
CSS that only affects the current component
Frequently Asked Questions
What is the difference between props and data?
Props are values passed into a component from its parent--they're like function parameters. Data is internal state owned by the component itself. Use props for configuration, data for internal state.
When should I use the Composition API?
Use the Composition API for all new Vue 3 projects. It provides better TypeScript support, enables logic reuse through composables, and keeps related code together. The Options API remains supported for legacy projects.
How do I share logic between components?
Extract shared logic into composable functions (Vue use functions). These are plain JavaScript functions that can use Vue's Composition API functions like ref(), computed(), and lifecycle hooks.
What is the scoped attribute in styles?
The scoped attribute ensures component styles only apply to that component's elements. Vue compiles this to CSS that targets the component with a unique data attribute, preventing style leakage.
Sources
- MDN Web Docs - Creating our first Vue component - Comprehensive guide on Vue component creation
- Vue.js Official Tutorial - Official Vue.js documentation and tutorials
- DEV Community - An Easy, Comprehensive and Practical Guide to Vue3 - Vue 3 practical guide with Composition API examples