NashTech Blog

Table of Contents

Reusable components are the foundation of scalable Vue 3 applications. By designing components that are flexible, predictable, and easy to maintain, you can reduce duplication and keep your codebase clean as it grows.

Keep Components Focused

A reusable component should have one clear responsibility. Instead of building large components that handle multiple concerns, split them into smaller ones.

Bad example (too much responsibility):

  • Fetching data
  • Formatting UI
  • Handling user actions

Good example:

  • One component displays data
  • Another handles data fetching
  • Logic is extracted into composables

Use Props for Configuration, Not Logic

Props should configure behavior, not control internal logic flow

<BaseButton :loading="isSaving" variant="primary" />

This keeps the component flexible without exposing internal details.

defineProps({
  loading: Boolean,
  variant: {
    type: String,
    default: 'default'
  }
});

Emit Events Instead of Mutating State

Reusable components should never modify parent state directly. Use events to communicate upward.

<BaseInput
  :model-value="email"
  @update:model-value="email = $event"
/>

This makes the component predictable and easy to reuse in different contexts.

Prefer v-model Contracts in Vue 3

Vue 3 allows custom v-model bindings, which makes components feel natural to use.

<MyInput v-model:value="username" />
defineEmits(['update:value']);

This creates a clear and standardized API for consumers of your component.

Extract Logic into Composables

When multiple components share behavior, extract the logic into a composable instead of duplicating code.

export function useToggle() {
  const isOpen = ref(false);
  const toggle = () => (isOpen.value = !isOpen.value);
  return { isOpen, toggle };
}

Composable functions improve reusability without coupling UI elements together.

Avoid Hard-Coded Styles and Content

Use slots to allow flexible content injection.

Reusable component (BaseCard.vue)

<template>
  <div class="card">
    <slot />
  </div>
</template>
<BaseCard>
  <template #header>Title</template>
  <p>Content goes here</p>
</BaseCard>

Slots allow components to adapt to different use cases without modification.

Without slots ❌:

<div class="card">
  <h3>Title</h3>
  <p>Fixed content</p>
</div>

Design Stable Component APIs

Reusable components should change rarely. A stable API (props, emits, slots) ensures that refactoring doesn’t break consumers.

Conclusion

Building reusable components in Vue 3 is about clarity, separation of concerns, and stable APIs. By leveraging props, emits, slots, composables, and Vue 3’s improved v-model, you can create components that scale with your application instead of slowing it down.

Picture of Tung Mai Xuan

Tung Mai Xuan

Leave a Comment

Your email address will not be published. Required fields are marked *

Suggested Article

Scroll to Top