Contenido del Artículo
Fundamentos de la Tecnología
Los Web Components son un conjunto de estándares web que permiten crear elementos HTML personalizados con funcionalidad encapsulada. Se componen de tres tecnologías clave:
- Custom Elements: Define nuevos elementos HTML
- Shadow DOM: Proporciona encapsulación de estilos y estructura
- HTML Templates: Permite crear fragmentos de markup reutilizables
Encapsulación
El Shadow DOM aísla estilos y DOM del documento principal
Reutilización
Componentes que funcionan en cualquier proyecto sin dependencias
Interoperabilidad
Funcionan con React, Vue, Angular y otros frameworks
// Registrar un nuevo elemento
class MiComponente extends HTMLElement {
constructor() {
super();
// Crear Shadow DOM
this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = `
<style>
:host { display: block; }
p { color: #2c3e50; }
</style>
<p>¡Hola desde mi componente!</p>
`;
}
}
customElements.define('mi-componente', MiComponente);
Los Web Components son compatibles con todos los navegadores modernos sin necesidad de polyfills
Tecnología | Función | Estado |
---|---|---|
Custom Elements | Definir nuevos elementos | Estándar |
Shadow DOM | Encapsulación | Estándar |
HTML Templates | Markup reutilizable | Estándar |
HTML Imports | Carga de componentes | Obsoleto |
Creando tu Primer Componente
Vamos a construir un botón personalizado con estado:
- Extiende la clase HTMLElement
- Usa el Shadow DOM para encapsulación
- Gestiona propiedades con observedAttributes
- Define métodos del ciclo de vida
class MiBoton extends HTMLElement {
static get observedAttributes() {
return ['disabled'];
}
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = `
<button>
<slot></slot>
</button>
<style>
button {
padding: 12px 24px;
background: #4285f4;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:disabled { opacity: 0.5; }
</style>
`;
this.button = this.shadowRoot.querySelector('button');
}
connectedCallback() {
this.button.addEventListener('click', this._onClick);
}
disconnectedCallback() {
this.button.removeEventListener('click', this._onClick);
}
attributeChangedCallback(name, oldVal, newVal) {
if(name === 'disabled') {
this.button.disabled = newVal !== null;
}
}
_onClick = () => {
this.dispatchEvent(new CustomEvent('boton-click', {
bubbles: true,
composed: true
}));
}
}
customElements.define('mi-boton', MiBoton);
Usa el componente en tu HTML: <mi-boton>Click Aquí</mi-boton>
Comunicación entre Componentes
Los componentes pueden comunicarse mediante:
- Atributos y propiedades
- Eventos personalizados
- Patrón de publicación/suscripción
- API de contexto (experimental)
// Disparar evento personalizado
this.dispatchEvent(new CustomEvent('actualizacion-datos', {
detail: { usuario: 'Juan', rol: 'admin' },
bubbles: true,
composed: true
}));
// Escuchar evento
document.addEventListener('actualizacion-datos', (e) => {
console.log('Datos recibidos:', e.detail);
});
Mejores Prácticas
Consejos para desarrollar componentes robustos:
Nomenclatura
Usa guión en nombres (ej: mi-componente) para diferenciar de elementos nativos
Encapsulación
Utiliza Shadow DOM para evitar conflictos de CSS
Accesibilidad
Implementa roles ARIA y propiedades accesibles
Rendimiento
Usa connectedCallback para inicialización diferida
Caso | Solución |
---|---|
Props complejas | Usar propiedades en lugar de atributos |
Temas personalizados | Variables CSS y ::part |
Renderizado dinámico | Slot elements y <template> |
Pruebas | Web Test Runner o Jest |
Ecosistema y Herramientas
Bibliotecas que mejoran la experiencia con Web Components:
// Ejemplo con Lit
import { LitElement, html, css } from 'lit';
class LitButton extends LitElement {
static styles = css`
button { /* estilos */ }
`;
render() {
return html`<button><slot></slot></button>`;
}
}
customElements.define('lit-button', LitButton);
Lit, Stencil y FAST amplían capacidades manteniendo estándares