Vue.js Components: Building Reusable UI

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.

Leave a comment

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.