WebComponents en Astro

Cómo crear WebComponents para utilizar en Astro


Como habrás observado en artículos anteriores, uno de los problemas que tenemos al trabajar con código Javascript, es que no tenemos una forma nativa y sencilla para ejecutar código Javascript sin que sea global a toda la página. Necesitamos una forma de encapsular nuestro Javascript. Realmente, si que existe. Son los WebComponents.

¿Qué son los WebComponents?

Los WebComponents son un conjunto de tecnologías (HTML, CSS y Javascript) que unidas nos permiten crear nuestras propias etiquetas HTML, y que de forma opcional, tengan una encapsulación real y funcionen a nivel local o de componente, sin necesidad de frameworks o librerías de terceros.

Si te interesa saber más, tenemos un curso especialmente dedicado a WebComponents.

WebComponents en Astro

Astro nos permite utilizar WebComponents nativos, simplificándolos de una forma muy ingeniosa, utilizando los propios componentes .astro para simplificarlos. Por ejemplo, veamos un componente que nos permite calificar un elemento de 0 a 5. He utilizado círculos de emoji, pero podría personalizarse con cualquier otra cosa.

El componente de .astro nos permite definir el value inicial y el icon para mostrar el rating. De esta forma, podríamos utilizarlo tal que así:

---
import CustomRating from "./components/CustomRating.astro";
---
<CustomRating value="3" />

El componente tomará el valor 3 y mostrará círculo rojo como emoji activado, ya que no he proporcionado otro. El componente se implementaría de la siguiente forma:

---
const { value = 2, icon = "🔴" } = Astro.props;
---

<custom-rating data-value={value} data-icon={icon}>
  <button></button>
</custom-rating>

<script>
  class CustomRating extends HTMLElement {
    connectedCallback() {
      const button = this.querySelector("button");
      let value = Number(this.dataset.value);
      let icon = this.dataset.icon;

      const updateButton = () => {
        button.textContent = icon?.repeat(value) + "⚫".repeat(5 - value);
      }
      updateButton();

      button?.addEventListener("click", () => {
        value = (value + 1) % 6;
        this.dataset.value = value;
        updateButton();
      });
    }

  }

  customElements.define("custom-rating", CustomRating);
</script>

Observa que <custom-rating> es un custom element, una etiqueta propia nuestra que se caracteriza porque lleva un guión - en su nombre. Las props las estamos guardando en los atributos data del elemento. Luego, en su interior hemos definido un <button> que de momento está vacío.

Bien, ahora vamos al código Javascript:

  • 1️⃣ Creamos una clase CustomRating que extiende de una etiqueta HTML normal.
  • 2️⃣ El método connectedCallback() se ejecuta al principio (al insertar en el DOM).
  • 3️⃣ Añadimos dentro del botón los iconos necesarios.
  • 4️⃣ Si el usuario hace click en el botón, aumentamos en uno value.
  • 5️⃣ Finalmente, no olvidar registrar el componente con customElements.define().

Como Astro procesa los bloques <script>, si utilizamos varias veces el componente desde Astro, la primera vez ejecutará el Javascript (que registra el componente), pero las siguientes sólo utilizará la parte de marcado, que es lo único que necesitamos para usarlo.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev