Todos los artículos
Integraciones· Avanzado

Web Components con Vue 3: distribuye un contador con defineCustomElement

Publica un contador Vue como Custom Element con estilos encapsulados y eventos para HTML.

LA

Luis Aldair Quispe Rios

3 min de lectura
Web Components con Vue 3: distribuye un contador con defineCustomElement

Objetivo y requisitos

Vamos a distribuir un contador escrito en Vue como un Custom Element que se pueda usar en HTML. defineCustomElement crea la clase del elemento y customElements.define registra su nombre. El consumidor no necesita montar una aplicación Vue, aunque el paquete generado sí incluye el runtime de Vue.

Parte de un proyecto Vue 3 con Vite, TypeScript y el plugin oficial de Vue. El sufijo .ce.vue activa el modo Custom Element del plugin para incluir el CSS del componente dentro del shadow DOM.

Counter.ce.vue completo

Guarda el archivo en src/Counter.ce.vue:

<script setup lang="ts">
import { ref } from 'vue'

const props = defineProps({ initial: { type: Number, default: 0 } })
const emit = defineEmits<{ change: [value: number] }>()
const count = ref(props.initial)

function increment() {
  count.value++
  emit('change', count.value)
}
</script>

<template>
  <button type="button" @click="increment">Contador: {{ count }}</button>
</template>

<style scoped>
button { padding: .75rem 1rem; border: 0; border-radius: .5rem; background: #047857; color: white; cursor: pointer; }
</style>

initial se lee al crear el contador; no representa un valor controlado que se sincronice después. Los eventos emitidos por Vue se convierten en CustomEvent y sus argumentos se entregan dentro de detail como un array.

Registra el elemento

En src/register.ts:

import { defineCustomElement } from 'vue'
import Counter from './Counter.ce.vue'

const VueCounter = defineCustomElement(Counter)
if (!customElements.get('vue-counter')) {
  customElements.define('vue-counter', VueCounter)
}

El nombre debe contener un guion. La comprobación evita registrar dos veces el mismo nombre si la entrada se carga de nuevo.

Compila una biblioteca

Para esta demostración, usa este vite.config.ts. No marca Vue como dependencia externa: así el HTML de prueba puede consumir un único módulo que incluye el runtime.

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  build: {
    lib: {
      entry: 'src/register.ts',
      formats: ['es'],
      fileName: () => 'vue-counter.js',
    },
  },
})

Ejecuta npm run build y sirve dist por HTTP. Puedes usar npx vite preview y su dirección de red local. Añade demo.html dentro de dist después de compilar:

<!doctype html>
<html lang="es">
  <meta charset="utf-8" />
  <title>Contador Vue en HTML</title>
  <script type="module" src="./vue-counter.js"></script>
  <vue-counter initial="2"></vue-counter>
  <p id="result" aria-live="polite">Pulsa el contador</p>
  <script type="module">
    document.querySelector('vue-counter').addEventListener('change', (event) => {
      document.getElementById('result').textContent = `Valor recibido: ${event.detail[0]}`
    })
  </script>
</html>

Resultado esperado y errores frecuentes

Abre /demo.html desde el servidor de preview: el botón empieza en 2 y el primer clic muestra 3 en el botón y en el párrafo externo. Inspecciona el shadow DOM para ver los estilos. Sirve el archivo por HTTP en lugar de abrirlo con file://.

Si los estilos desaparecen, comprueba el sufijo .ce.vue. Si el consumidor no recibe el número, usa event.detail[0]. Si el registro falla, revisa el nombre con guion y que no esté definido antes. Al integrar el elemento dentro de otra app Vue, configura compilerOptions.isCustomElement para que el compilador lo trate como elemento nativo.

Esta distribución incluye Vue y tiene un coste de descarga: mide el paquete antes de adoptar el patrón para muchos widgets. No presupongas que el componente queda libre de dependencias solo por usarlo en HTML. Consulta Vue y Web Components.

Sigue leyendo

¿Cómo integrar Tailwind 4 en Vue.js 3 + Vite?

¿Cómo integrar Tailwind 4 en Vue.js 3 + Vite?

Configura Tailwind CSS 4 en Vue 3 con los plugins de Vue y Tailwind para Vite.
Tailwind CSS 4 con Vue CLI: guía para proyectos existentes

Tailwind CSS 4 con Vue CLI: guía para proyectos existentes

Mantén un proyecto existente con Vue CLI y compila Tailwind 4 sin desactivar la optimización de producción.
Autenticación con Google en Vue 3 y VueFire

Autenticación con Google en Vue 3 y VueFire

Conecta Firebase Auth con VueFire y añade acceso con Google, cierre de sesión y errores visibles.