Ciclo de vida de un WebComponent

Fases por las que pasa un WebComponent

Durante la carga de una página y el tiempo en el que la utilizamos, los WebComponent pasan por una serie de fases que se conocen como el ciclo de vida del WebComponent. Conociendo este ciclo y las fases que lo componen, es mucho más fácil predecir el funcionamiento de los WebComponents y trabajar con ellos.

  • Fase 1: Componente no creado, ni insertado en el DOM (Documento HTML)
  • Fase 2: Componente creado, pero no insertado en el DOM (Etiqueta HTML)
  • Fase 3: Componente creado e insertado en el DOM (Documento HTML)

En el siguiente diagrama se puede ver los saltos de fase utilizando unos métodos especiales que existen y podemos utilizar en las clases de los WebComponents:

WebComponents: Lifecycle Diagram

Como hemos comentado, estos métodos especiales los podemos definir dentro de la clase del componente. Sin embargo, dichos métodos no se llaman manualmente (como los que creamos los desarrolladores), sino que son unos métodos que se disparan automáticamente cuando el componente llega a una fase concreta de su «ciclo de vida».

Los métodos son los siguientes:

Característica ¿Cuándo se ejecuta?
constructor() Cuando se crea el custom element, y previamente ha sido definido en el registro.
connectedCallback() Cuando el custom element se ha insertado en el documento HTML (DOM).
disconnectedCallback() Cuando el custom element se ha eliminado del documento HTML (DOM).
adoptedCallback() Cuando el custom element se ha movido a un nuevo documento (común en iframes).
attributeChangedCallback() Cuando se ha modificado un atributo observado del componente. Ver atributos

Veamos cada uno de estos métodos detenidamente.

Métodos del ciclo de vida

Construcción del componente

Aunque la etiqueta HTML personalizada sea un custom element, inicialmente el navegador la considera un HTMLElement, es decir, una etiqueta HTML normal. Si se cumple la condición de que está definida en el registro global del navegador, entonces intentará actualizarla a un custom element.

El método constructor() en un WebComponent tiene la misma función que en una clase de programación. Se ejecutará cada vez que se cree un custom element particular, y que previamente haya sido definido en el registro global del navegador con customElements.define(). Por lo tanto, si creamos varias etiquetas de un componente (instancias), se ejecutará una vez por cada una de ellas.

Esto ocurrirá de forma automática si el custom element en cuestión se creó después de haber sido registrado mediante customElements.define(). En caso contrario, tendremos que hacerlo de forma manual mediante customElements.upgrade(). Tienes más información en el artículo del registro de Custom Elements.

El objetivo del constructor es hacer ciertas tareas de inicialización rápidas o tareas iniciales, como la creación del Shadow DOM (lo veremos más adelante). Es esencial que en el constructor del componente se hagan sólo las tareas más prioritarias y ligeras. Como norma general, si es posible aplazar lógica al método connectedCallback(), mejor.

En el caso de incluir lógica en el constructor que pueda llegar a modificar el DOM o los atributos de un componente, podría afectar al rendimiento o aparecernos errores como el siguiente:

Uncaught DOMException: Failed to construct 'CustomElement': The result must not have children

Inserción en el DOM

El método connectedCallback() es una suerte de segundo constructor que se ejecuta cuando el custom element es conectado al documento HTML (DOM), es decir, cuando el componente es insertado o añadido al documento HTML.

Piensa, por ejemplo, que podemos crear un elemento HTML personalizado en una variable, que no esté incluido en el documento HTML:

// Custom Element registrado (el navegador ya lo conoce)
customElements.define("app-element", AppElement);

// Custom Element creado -> Se ejecuta el constructor()
const component = document.createElement("app-element");

// Custom Element añadido al DOM -> Se ejecuta el connectedCallback()
document.body.appendChild(component);

Esta característica lo hace realmente útil para incluir, por ejemplo, tareas relacionadas con la renderización o dibujo visualmente. Por esta razón, también resulta interesante desplazar a este método ciertas tareas que es posible que no lleguen a necesitarse de manera inmediata.

Ten en cuenta que si un custom element es movido a otra parte del DOM, se desconectará y volverá a conectarse al DOM, pasando por los métodos connectedCallback() y disconnectedCallback() correspondientes.

Eliminación del DOM

Por contrapartida, el método connectedCallback() tiene un método opuesto o contrario: disconnectedCallback(). Mientras que el primero es llamado cuando insertas un custom element en el documento HTML, el último es llamado cuando un custom element es eliminado del DOM del documento HTML.

// Localizamos un componente en el documento HTML
const element = document.querySelector("app-element");

// Eliminamos el Custom Element -> Se ejecuta disconnectedCallback()
element.remove();

El método disconnectedCallback() puede ser realmente útil para realizar tareas importantes de finalización que, de lo contrario, estarían consumiendo recursos respecto a ese elemento.

Mover a otro documento

El método adoptedCallback(), de un uso menos frecuente, tiene sentido cuando se trabaja en contextos multidocumento, y se dispara cuando un custom element se mueve de un documento HTML a otro documento HTML diferente. Para moverlo, se utiliza el método .adoptNode().

Este método es muy útil cuando se trabaja con elementos <iframe>, por ejemplo.

Tabla de contenidos