Vue Web Component Wrapper

1.7.7 · active · verified Sun Apr 19

vue-web-component-wrapper is a Vue 3 plugin that facilitates the creation of reusable web components (custom elements) from full-fledged Vue applications. The current stable version is 1.7.7, with frequent patch and minor releases addressing bug fixes and introducing new features. This library differentiates itself by providing comprehensive support for the broader Vue ecosystem, including seamless integration with state management (Vuex, Pinia), routing (Vue Router), internationalization (Vue I18n), and validation (VeeValidate). It also offers robust compatibility with popular CSS frameworks like Tailwind CSS, Bootstrap, and Vuetify, alongside support for CSS preprocessors and scoped styles. Key features include Shadow DOM encapsulation, Vue DevTools integration, full slot and `v-model` support, event emitting, `provide`/`inject`, and options for fine-grained control over Shadow DOM behavior and CSS styling (e.g., `:root` to `:host` replacement). It also supports async initialization and loader mechanisms.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to define a basic Vue 3 component, create a Vue application instance from it, and then use `vue-web-component-wrapper` to register it as a custom element. It showcases prop passing, event emitting, and slot handling within the web component context.

import { createApp, defineComponent } from 'vue';
import { wrap } from 'vue-web-component-wrapper';

const MyVueComponent = defineComponent({
  props: {
    message: String,
    count: { type: Number, default: 0 }
  },
  emits: ['increment'],
  data() {
    return {
      internalCount: this.count
    };
  },
  methods: {
    increment() {
      this.internalCount++;
      this.$emit('increment', this.internalCount);
    }
  },
  template: `
    <div style="padding: 1rem; border: 1px solid #1a73e8; border-radius: 4px; margin-bottom: 1rem;">
      <h3>Hello from Vue Web Component!</h3>
      <p>Prop Message: <strong>{{ message }}</strong></p>
      <p>Current Count: <strong>{{ internalCount }}</strong></p>
      <button @click="increment" style="padding: 8px 16px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">Increment Count</button>
      <slot name="footer"></slot>
    </div>
  `,
});

const app = createApp(MyVueComponent);

const WebComponent = wrap(app, MyVueComponent, {
  props: {
    message: { type: String, default: 'Default Message' },
    count: { type: Number, default: 0 }
  },
  emits: ['increment'],
  // Example of wrapper options
  disableShadowDOM: false, // Keep Shadow DOM for encapsulation
  replaceCssRootToHost: true // Essential for :root styles within Shadow DOM
});

// Register the custom element in the browser's CustomElementRegistry
customElements.define('my-vue-counter', WebComponent);

// Example HTML usage:
// <my-vue-counter message="Initial Web Component" count="5"></my-vue-counter>
// <my-vue-counter message="Another instance with slot content">
//   <p slot="footer" style="color: gray; font-size: 0.9em;">This is content for the footer slot.</p>
// </my-vue-counter>

view raw JSON →