Crea elementos HTML personalizables con su propia maquetación, estilos e interactividad.
Un Web Component es una tecnología de HTML que permite crear elementos HTML personalizados para encapsularlos y reutilizarlos en distintas aplicaciones web. A través de Web Components, los desarrolladores pueden definir elementos con comportamiento y estilo propios, sin preocuparse de conflictos con el resto del documento HTML.
Por ejemplo, en lugar de usar un componente HTML nativo como <button>
, puedes definir un componente personalizado llamado <custom-button>
que tenga un diseño y funcionalidad únicos.
Los Web Components se pueden descomponer básicamente en cuatro especificaciones:
Primero hay que añadir las etiquetas de nuestro Web Component dentro del código HTML de nuestra página:
<my-custom-element></my-custom-element>
Luego, para definir el Web Component, seguimos estos pasos en un archivo JavaScript:
HTMLElement
o sus subclases (HTMLButtonElement
, HTMLDivElement
, etc.).customElements.define
.// Definir el componenteclass MyCustomElement extends HTMLElement { constructor() { super(); // Llamar al constructor del HTMLElement const shadow = this.attachShadow({ mode: 'open' }); // Adjuntar Shadow DOM const div = document.createElement('div'); div.textContent = '¡Hola desde Web Component!'; div.style.color = 'blue'; shadow.appendChild(div); // Agregar contenido al Shadow DOM }}
// Registrar el elementocustomElements.define('my-custom-element', MyCustomElement);
Si miras el código HTML de la página en el navegador verás el componente renderizado:
<my-custom-element> #shadow-root (open) <div style="color: blue;">¡Hola desde Web Component!</div></my-custom-element>
Los Web Components tienen métodos de ciclo de vida que permiten reaccionar a cambios en su estado o en el DOM:
connectedCallback
: Se ejecuta cuando el componente es agregado al DOM.disconnectedCallback
: Se ejecuta cuando el componente es eliminado del DOM.attributeChangedCallback
: Se ejecuta cuando uno de los atributos definidos cambia.adoptedCallback
: Se ejecuta cuando el componente se mueve a otro documento.Ejemplo de un Web Component con funciones de ciclo de vida:
<lifecycle-example></lifecycle-example>
El código JavaScript:
class LifecycleExample extends HTMLElement { constructor() { super(); console.log('Constructor ejecutado'); }
connectedCallback() { console.log('Elemento agregado al DOM'); }
disconnectedCallback() { console.log('Elemento eliminado del DOM'); }
attributeChangedCallback(name, oldValue, newValue) { console.log(`Atributo ${name} cambiado de ${oldValue} a ${newValue}`); }
static get observedAttributes() { return ['data-example']; // Especificar atributos que serán monitoreados }}
customElements.define('lifecycle-example', LifecycleExample);
Si cargas la página y miras la consola verás el orden en que se llama cada callback.
Veamos otro ejemplo práctico. En este caso creamos un contador que aumenta al hacer clic en un botón:
En tu HTML añadimos el componente:
<counter-component></counter-component>
Y la definición del componente en JavaScript:
class CounterComponent extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.count = 0;
// Crear contenido del componente this.shadowRoot.innerHTML = ` <style> button { background-color: #007BFF; color: white; border: none; padding: 10px 20px; cursor: pointer; } button:hover { background-color: #0056b3; } </style> <div> <p>Contador: <span id="count">${this.count}</span></p> <button id="increment">Incrementar</button> </div> `; }
connectedCallback() { this.shadowRoot.querySelector('#increment').addEventListener('click', () => { this.count++; this.shadowRoot.querySelector('#count').textContent = this.count; }); }
disconnectedCallback() { this.shadowRoot.querySelector('#increment').removeEventListener('click'); }}
customElements.define('counter-component', CounterComponent);
Aquí puedes ver el ejemplo en acción:
<!DOCTYPE html><html lang="es">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Ejemplo Web Component</title> <style>
</style></head>
<body> <counter-component></counter-component> <script>
class CounterComponent extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.count = 0;
// Crear contenido del componente this.shadowRoot.innerHTML = ` <style> button { background-color: #007BFF; color: white; border: none; padding: 10px 20px; cursor: pointer; } button:hover { background-color: #0056b3; } </style> <div> <p>Contador: <span id="count">${this.count}</span></p> <button id="increment">Incrementar</button> </div> `; }
connectedCallback() { this.shadowRoot.querySelector('#increment').addEventListener('click', () => { this.count++; this.shadowRoot.querySelector('#count').textContent = this.count; }); }
disconnectedCallback() { this.shadowRoot.querySelector('#increment').removeEventListener('click'); } }
customElements.define('counter-component', CounterComponent); </script></body>
</html>
Hemos visto qué es un Web Component, sus propiedades básicas y varios ejemplos. Este tipo de componentes pueden ser muy útiles en aplicaciones web, no requieren dependencias, son encapsulados y son fácilmentee reutilizables.