Los web componentes son una serie de tecnologías alineadas a una especificación estándar que nos permiten re-utilizar elementos HTML personalizados, que, en otras palabras, es lo hoy en día llamamos componentes. Esto es muy similar a lo que podemos hacer con librerías como React, Vue y Angular, pero con la gran diferencia de que estos funcionan de manera nativa.

Especificaciones

A continuación vamos a describir las tres especificaciones actuales:

HTML Imports, ES Modules y HTML Modules

Es importante recordar que la especificación original mencionaba los HTML Imports como la cuarta tecnología. Sin embargo, los navegadores consideraron que los ES Modules podrían ser la solución alternativa. Así,  a partir de la versión 73 de Google Chrome, esta tecnología se volvió obsoleta. Hoy por hoy, se está trabajando en una nueva propuesta llamada HTML Modules que pretende complementar ES Modules e integrar HTML Imports.

Más información

Custom Elements

Con Custom Elements podemos crear elementos HTML de manera personalizada. Por ejemplo, así como tenemos <div>, <span> e <input> podemos crear un elemento llamado <primary-button> que, al ser usado, nos mostrará un botón con las características personalizadas que le hayamos especificado.

Con este ejemplo, cada vez que insertemos el elemento <primary-button> se mostrará el botón azul que vemos arriba. Como podemos ver, estamos aplicando estilos en línea (inline) al contenido de nuestro Custom Element, aunque también podríamos aplicar estilos directamente al Custom Element desde un archivo CSS.

Hay dos tipos de Custom Elements:

  • Autonomous custom elements: estos son elementos independientes que casi siempre se heredan de HTMLElement, como en el ejemplo anterior.
  • Customized built-in elements: estos son elementos que heredan las propiedades de elementos ya definidos como HTMLParagraphElement o HTMLUListElement. Pueden ser útiles para usar las funcionalidades y comportamientos que provienen del elemento heredado.

Por ejemplo si queremos hacer una lista que tenga propiedades extra:

// En este caso estamos heredando del elemento Unordered List 
class DynamicList extends HTMLUListElement { }

// Y también se debe especificar de qué elemento se hereda en la definición
customElements.define('dynamic-list', DynamicList, { extends: "ul" });
<!-- Finalmente, el uso en el HTML varía un poco, ya que se usa el atributo is -->
<ul is="dynamic-list"></ul>

En el repositorio de MDN (Mozilla Developer Network) podemos ver un ejemplo completo.

Actualmente, muchas de las librerías de JavaScript soportan el uso de Web Components dentro de ellas. Se puede ver el estado de su soporte aquí.

Convención del nombre de los Custom Elements

Es importante que el nombre del Custom Element incluya un "-" (guión) pues, de otra manera, el navegador tomará el elemento como desconocido.

Más información

Shadow DOM

Con Shadow DOM tenemos la posibilidad de encapsular estilos y markups de un elemento. Mientras que el DOM (Document Object Model) en el documento es también llamado Light DOM, al DOM dentro de un shadowRoot se le llama Shadow DOM.

En este ejemplo tenemos dos <div> con un elemento <button>, respectivamente. Sin embargo, vemos que, en vez de mostrarse los botones "Shadow DOM" y "Light DOM", el primero tiene "Shadow Root" como texto y, además, posee unos estilos diferentes. Esto es precisamente porque mediante el Shadow DOM hemos encapsulado los estilos y el contenido del botón dentro del shadowRoot.

Modo abierto y cerrado

A la hora de llamar el método attachShadow podemos configurar si queremos que el mode (modo) sea open (abierto) o closed (cerrado). La diferencia es que el modo open nos permite acceder al Shadow DOM desde el contexto principal de la página mediante el Element.shadowRoot. Si, por el contrario, el modo es closed el Element.shadowRoot va a retornar null.

Más información

HTML Templates

Con HTML Templates podemos crear templates de forma nativa que no son pintados (rendered) antes de ser usados en nuestra página. De esta manera, obtendremos un mayor rendimiento en el procesamiento inicial de la página.

En el ejemplo anterior definimos un template llamado card-template y solo hasta después de leer nuestra lista de lugares es que hacemos uso del template. Para ello, se hace una clonación de este y posteriormente una inserción en el documento donde queremos mostrar nuestro template.

Flexibilidad con Slots

Los slots son como pequeños placeholders (comodines). Estos pueden tener una identificación mediante el atributo name y, de esta manera, podemos definir cómo queremos estructurar la información cuando la recibimos desde un Custom Element.

Un ejemplo completo

Ya que hemos hablado de cada una de las especificaciones y demostramos cómo se pueden usar de manera independiente, veamos su uso en conjunto para crear un Web Component en el "mundo real".

Como podemos notar, en este ejemplo estamos usando los tres conceptos para crear un Custom Element llamado beauty-card que recibe una imagen, un título y una descripción. Además, hemos aplicado una regla en la que, si no encuentra una imagen, se agrega otra por defecto.

Aplicar estilos a los elementos slot

En el ejemplo anterior fue necesario usar el selector beauty-card img para poder aplicar los debidos estilos a las imágenes que se pasaron mediante los elementos slot. Aparentemente, no hay forma de modificar los estilos de manera interna desde el Custom Element.

Referencias