Table of contents [Show]
- Introduction: Why Reusable Components Matter
- Step 1: Setting Up Your Vue.js Project
- Step 2: Creating a Simple Reusable Component
- Step 3: Using the Reusable Button Component
- Step 4: Leveraging Props for Flexibility
- Step 5: Using Slots for Content Injection
- Step 6: Best Practices for Reusable Components
- Step 7: Creating a Library of Components
- Step 8: Real-World Example – Dashboard UI
- Conclusion
Introduction: Why Reusable Components Matter
When I first started working with Vue.js, I was amazed at how quickly I could build UI elements. But soon, I realized that many components were duplicated across pages. That’s when the concept of reusable components became my best friend.
Reusable components help:
- Reduce code duplication
- Maintain consistent UI across the app
- Enable easier testing and debugging
- Improve scalability and maintainability
In this tutorial, we’ll explore how to build reusable Vue components effectively and follow best practices that make your projects robust.
Step 1: Setting Up Your Vue.js Project
If you don’t have a project yet, start with Vite for a fast development environment:
npm init vue@latest reusable-components-demo
cd reusable-components-demo
npm install
npm run dev
Now your environment is ready for component creation.
Step 2: Creating a Simple Reusable Component
Let’s start by creating a simple Button.vue component that can be reused with different labels and styles.
<template>
<button : @click="$emit('click')">
<slot>Default Button</slot>
</button>
</template>
<script setup>
import { computed } from "vue";
const props = defineProps({
type: {
type: String,
default: "primary"
}
});
const btnClass = computed(() => {
return {
'btn-primary': props.type === 'primary',
'btn-secondary': props.type === 'secondary'
}
});
</script>
<style scoped>
.btn-primary { background-color: #3490dc; color: #fff; padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; }
.btn-secondary { background-color: #6c757d; color: #fff; padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; }
</style>
Explanation:
- Uses
propsto customize button type. - Emits
clickevent for parent interaction. - Uses a default slot for flexibility.
Let’s use our reusable Button.vue component in App.vue.
App.vue
<template>
<div>
<h1>Reusable Button Example</h1>
<Button type="primary" @click="handleClick">Primary Button</Button>
<Button type="secondary" @click="handleClick">Secondary Button</Button>
</div>
</template>
<script setup>
import Button from './components/Button.vue';
const handleClick = () => {
alert("Button clicked!");
};
</script>
Result: Both buttons are using the same component but render differently based on the type prop and slot content.
Step 4: Leveraging Props for Flexibility
Props allow parent components to pass data to reusable components, making them versatile.
Example: Card Component with Props
<template>
<div >
<h3>{{ title }}</h3>
<p>{{ content }}</p>
</div>
</template>
<script setup>
const props = defineProps({
title: { type: String, required: true },
content: { type: String, required: true }
});
</script>
<style scoped>
.card { border: 1px solid #ccc; padding: 16px; border-radius: 8px; margin-bottom: 12px; }
</style>
Now we can create multiple cards dynamically with different titles and content.
Step 5: Using Slots for Content Injection
Slots allow parent components to inject content into child components, making them even more reusable.
Example: Modal Component with Slots
<template>
<div >
<header><slot name="header">Default Header</slot></header>
<main><slot>Default Content</slot></main>
<footer><slot name="footer">Default Footer</slot></footer>
</div>
</template>
<script setup></script>
<style scoped>
.modal { background: #fff; padding: 16px; border-radius: 8px; border: 1px solid #ddd; }
</style>
Usage: Inject custom content for header, body, and footer using named slots.
Step 6: Best Practices for Reusable Components
- Keep components focused: Each component should handle a single responsibility.
- Use props and slots: Make components flexible and avoid hardcoded content.
- Name components clearly: Use descriptive names like
UserCardorPrimaryButton. - Encapsulate styles: Use scoped styles to avoid conflicts.
- Emit events thoughtfully: Keep parent-child communication clear and predictable.
- Document component API: Props, events, and slots should be clearly described for team use.
- Write unit tests: Ensure components behave consistently across usage scenarios.
Step 7: Creating a Library of Components
Once you have reusable components, you can organize them into a component library:
- Create a
components/folder with subfolders likebuttons/,cards/,modals/. - Export all components from an
index.jsfile for easy imports. - Use consistent naming and file structure to make it scalable for larger projects.
Step 8: Real-World Example – Dashboard UI
Combine reusable buttons, cards, and modals to build a dashboard:
<template>
<div >
<Button type="primary" @click="showModal = true">Add User</Button>
<Card v-for="user in users" :key="user.id" :title="user.name" :content="user.email" />
<Modal v-if="showModal" @close="showModal = false">
<template #header><h3>New User</h3></template>
<form>...form fields...</form>
<template #footer><Button @click="showModal=false">Cancel</Button></template>
</Modal>
</div>
</template>
<script setup>
import { ref } from 'vue';
import Button from './components/Button.vue';
import Card from './components/Card.vue';
import Modal from './components/Modal.vue';
const showModal = ref(false);
const users = ref([
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
]);
</script>
Result: A fully data-driven dashboard built using reusable components and following best practices.
Conclusion
Reusable components are the backbone of scalable Vue.js applications. By leveraging props, slots, and clear component patterns, you can create flexible, maintainable, and scalable UI elements. Following best practices ensures that your components remain easy to use, test, and extend as your project grows. Start small, build a component library, and watch your Vue applications become cleaner, faster, and more efficient.






