Components are the heart of Vue.js. Build once, reuse everywhere. Here’s how to create flexible, maintainable Vue components.
Basic Component
<template>
<button class="btn" :class="variant" @click="$emit('click')">
<slot>Button</slot>
</button>
</template>
<script>
export default {
name: 'BaseButton',
props: {
variant: {
type: String,
default: 'primary',
validator: v => ['primary', 'secondary', 'danger'].includes(v)
}
}
};
</script>
<style scoped>
.btn { padding: 0.5rem 1rem; border-radius: 4px; }
.primary { background: #0078d4; color: white; }
.secondary { background: #6c757d; color: white; }
.danger { background: #dc3545; color: white; }
</style>
Props Validation
props: {
// Basic type
title: String,
// Required
id: {
type: Number,
required: true
},
// Default value
status: {
type: String,
default: 'active'
},
// Custom validator
priority: {
type: Number,
validator: value => value >= 1 && value <= 5
}
}
Custom Events
<!-- Child component -->
<template>
<form @submit.prevent="submit">
<input v-model="email" />
<button type="submit">Submit</button>
</form>
</template>
<script>
export default {
data() {
return { email: '' };
},
methods: {
submit() {
this.$emit('submitted', { email: this.email });
}
}
};
</script>
<!-- Parent -->
<EmailForm @submitted="handleSubmit" />
Slots for Flexibility
<!-- Card component -->
<template>
<div class="card">
<div class="card-header">
<slot name="header">Default Header</slot>
</div>
<div class="card-body">
<slot></slot>
</div>
<div class="card-footer">
<slot name="footer"></slot>
</div>
</div>
</template>
<!-- Usage -->
<Card>
<template #header>My Title</template>
<p>Card content goes here</p>
<template #footer>
<button>Action</button>
</template>
</Card>
Component Organization
- Keep components small and focused
- Use scoped styles to avoid CSS conflicts
- Prefix base components (BaseButton, BaseInput)
- Validate props for better dev experience
References
Discover more from C4: Container, Code, Cloud & Context
Subscribe to get the latest posts sent to your email.