Vue First Component

Master the fundamentals of building reusable Vue.js components with Single File Components, props, and the Composition API

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 optional scoped attribute 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 scoped attribute 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.

Vue Component Essentials

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.

Build Modern Vue.js Applications

Our team creates performant, scalable web applications using Vue 3 and the Composition API. From simple components to complex applications, we deliver quality code.

Sources

  1. MDN Web Docs - Creating our first Vue component - Comprehensive guide on Vue component creation
  2. Vue.js Official Tutorial - Official Vue.js documentation and tutorials
  3. DEV Community - An Easy, Comprehensive and Practical Guide to Vue3 - Vue 3 practical guide with Composition API examples