Skip to main content

Command Palette

Search for a command to run...

Vue.js Component Design Patterns-Building a Reusable Component Library

Updated
5 min read
Vue.js Component Design Patterns-Building a Reusable Component Library

Creating a reusable component library in Vue.js is key to improving code reusability and maintainability. Below are design patterns and examples demonstrating how to build reusable Vue components.

1. Single File Component (SFC)

Vue.js components are typically Single File Components, combining HTML, CSS, and JavaScript. Here’s an example of a reusable component:

<template>
  <div class="my-component">
    <h3>{{ title }}</h3>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  props: {
    title: String,
    message: String,
  },
};
</script>

<style scoped>
.my-component {
  /* Custom styles */
}
</style>

In this example, title and message are passed as props, allowing external customization of the component’s title and message.

2. Component Props and Default Values

Props enable components to accept external data, with default values set using the default property:

props: {
  myProp: {
    type: String,
    default: 'Default value',
  },
},

3. Custom Events

Use $emit to dispatch custom events, facilitating communication between parent and child components:

methods: {
  handleClick() {
    this.$emit('my-event', 'This is event data');
  },
},

4. Slots

Slots allow parent components to inject content into child components:

<template>
  <div class="container">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

Parent component usage:

<MyComponent>
  <template v-slot:header>
    <h1>This is the header</h1>
  </template>
  <p>This is the main content</p>
  <template v-slot:footer>
    <p>This is the footer</p>
  </template>
</MyComponent>

5. Scoped Slots

Scoped slots allow passing functions or data for more complex slot scenarios:

<template>
  <ul>
    <li v-for="(item, index) in items" :key="index">
      <slot :item="item" :index="index"></slot>
    </li>
  </ul>
</template>

Parent component usage:

<MyList :items="list">
  <template v-slot:default="{ item, index }">
    <span>{{ item.text }} ({{ index }})</span>
  </template>
</MyList>

6. State Management (Vuex or Pinia)

For complex applications, use Vuex or Pinia to centrally manage shared state, enhancing component reusability.

7. Higher-Order Components (HOCs)

While Vue.js doesn’t natively support HOCs, you can mimic them using functional components and the Composition API:

function withLoading(ChildComponent) {
  return {
    extends: ChildComponent,
    data() {
      return {
        isLoading: false,
      };
    },
    methods: {
      fetchData() {
        this.isLoading = true;
        // Data fetching logic
        // ...
        this.isLoading = false;
      },
    },
  };
}

export default withLoading(MyComponent);

8. Building and Publishing a Component Library

Building a component library involves tools like Vue CLI, Rollup, or Webpack. Vue CLI offers the vue-cli-service build --library command to create a library. After publishing to npm, other projects can install your library using npm install.

9. Component Abstraction and Encapsulation

To enhance reusability, break components into smaller, focused parts. For example, a form component can be split into input fields, buttons, and validators, each reusable independently or combined into new forms.

<!-- InputField.vue -->
<template>
  <input :type="type" :value="value" @input="handleChange" :class="inputClasses" />
</template>

<script>
export default {
  props: {
    type: {
      type: String,
      default: 'text',
    },
    value: {
      type: [String, Number],
      default: '',
    },
    inputClasses: {
      type: String,
      default: '',
    },
  },
  methods: {
    handleChange(event) {
      this.$emit('input', event.target.value);
    },
  },
};
</script>

10. Component Reusability and Configurability

Design components with configurability in mind, allowing customization via props or slots. For example, a card component can accept properties like background color and border width.

<!-- Card.vue -->
<template>
  <div :class="cardClasses" :style="cardStyle">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    backgroundColor: {
      type: String,
      default: '#fff',
    },
    borderColor: {
      type: String,
      default: '#ccc',
    },
    borderWidth: {
      type: Number,
      default: 1,
    },
  },
  computed: {
    cardClasses() {
      return {
        card: true,
        // Compute class names based on props
      };
    },
    cardStyle() {
      return {
        backgroundColor: this.backgroundColor,
        border: `${this.borderWidth}px solid ${this.borderColor}`,
      };
    },
  },
};
</script>

11. Component Extensibility

Design components for future extensibility using slots and events to enable interaction with other components or features. For example, a modal component can include header, content, and footer slots for varied use cases.

<!-- Modal.vue -->
<template>
  <div class="modal" @click="handleOutsideClick">
    <div class="modal__content">
      <slot name="header"></slot>
      <div class="modal__body">
        <slot></slot>
      </div>
      <slot name="footer"></slot>
    </div>
  </div>
</template>

<script>
export default {
  methods: {
    handleOutsideClick(event) {
      if (!this.$el.contains(event.target)) {
        this.$emit('close');
      }
    },
  },
  mounted() {
    document.addEventListener('mousedown', this.handleOutsideClick);
  },
  beforeDestroy() {
    document.removeEventListener('mousedown', this.handleOutsideClick);
  },
};
</script>

12. Component Documentation and Examples

Write clear documentation covering component purpose, usage examples, props, events, and slots to help developers understand and use your library effectively.

13. Testing and Quality Assurance

Write unit and integration tests to ensure components work correctly in various scenarios, improving reliability by catching and fixing issues during development.

Component Lazy Loading

Optimize performance with Vue Router’s lazy loading, loading components only when needed, especially for rarely used components in large libraries:

// In Vue Router configuration
{
  path: '/some-path',
  component: () => import('@/components/SomeLargeComponent.vue'),
},

On-Demand Component Imports

When using third-party libraries, import only needed features with ES modules to avoid loading unnecessary code:

import { DatePicker } from 'vue-datepicker';

Design System and Style Guide

Create a design system and style guide defining component styles, interactions, and behaviors to ensure consistency across the library, improving code quality.

Version Control and Release Process

Use Git for version control and follow Semantic Versioning (SemVer) for releasing new library versions. Provide detailed changelogs with each release to inform users of changes.

Continuous Integration/Continuous Deployment (CI/CD)

Set up CI/CD pipelines to automate testing, building, and deploying the component library, ensuring validated commits and rapid production releases.

Code Review

Implement code reviews to maintain library quality and consistency, using team audits or platforms like GitHub’s Pull Requests.

Feedback and Improvement

Encourage feedback from users and team members to fix issues and enhance the library. Establish a community or forum for users to discuss and share experiences.

By applying these strategies, you can create a robust, efficient, and maintainable Vue component library. Continuously learn and refine component design to meet evolving needs and best practices.

Web Development

Part 14 of 46

The content covers the three basics of HTML/CSS/JS/TS, modular development, mainstream frameworks (Vue, React, Angular, Svelte), build tools, browser plug-in development, Node.js backend practice, Next.js/Nest.js and other popular technologies.

Up next

PWA Offline-First Strategies-Key Steps to Enhance User Experience

Progressive Web Apps (PWAs) implement offline-first strategies using Service Workers and the Cache API, enabling access to parts or all of a website’s content without an internet connection. 1. Create a Service Worker File (service-worker.js) self.ad...

More from this blog

T

Tianya School Technical Articles

48 posts

Welcome to our tech publication, where we share high-quality content on full-stack development, frontend/backend/web3/AI, and engineering best practices.