Estructura y carga de componentes

Ahora que ya conocemos las bases de los Custom Elements (la parte de WebComponents que permite crear nuestras propias etiquetas), toca comenzar a crear componentes básicos para ir viendo la estructura que podemos seguir para dotarle de funcionalidad.

En este artículo vamos a ver como preparar una estructura de archivos utilizando WebComponents, como crear un componente y como cargarlo y utilizarlo dependiendo si nos interesa hacerlo desde HTML o desde Javascript.

Estructura de componentes

Estructura de archivos

Quizás, lo primero que deberíamos tener claro es la estructura de carpetas y archivos que vamos a tener para crear nuestros componentes.

En principio, esta «arquitectura» depende mucho de lo que queramos hacer y es muy variable dependiendo de nuestros objetivos, pero vamos a partir de ejemplo sencillo de base, donde app es el nombre de la carpeta de nuestro proyecto:

- app
   +-- components/
   |     +-- AppElement.js
   +-- index.html
   +-- index.js

Partimos de un archivo index.html (el punto de entrada de la aplicación). Dicho archivo HTML puede cargar directamente (como veremos más adelante) el componente AppElement.js, que se encuentra dentro de la carpeta components/, o puede cargarlo a través de un fichero index.js que hace de fichero «centralizador».

Nuevamente, dejar claro que esto es sólo un ejemplo de partida y que esta estructura puede variar mucho dependiendo del proyecto y necesidades.

Crear un WebComponent

Para empezar, vamos a crear el componente básico mínimo necesario para hacerlo funcionar. Como ya hemos visto, esta formado de una clase que debe extender de HTMLElement, y asociarlo por medio de customElements.define() con el nombre de una etiqueta HTML (nuestro custom element):

class AppElement extends HTMLElement {

  constructor() {
    super();
  }

}

customElements.define("app-element", AppElement);

Como buena práctica, este fichero suele nombrarse igual que la clase, AppElement.js y suele colocarse en una carpeta components/, aunque esto puede depender de la arquitectura utilizada.

Nota: En los casos que el constructor del componente no tenga ninguna lógica (solo incluya el super(), como en el ejemplo anterior) podemos ahorrarnos escribir el constructor, ya que es el comportamiento que tiene por defecto.

Cargar componente desde HTML

Una vez tengamos un WebComponent creado, lo que toca es aprender los pasos para cargarlo y utilizarlo. Probablemente, la forma más fácil de hacerlo, es cargándolo desde el HTML de la siguiente forma:

  • Cargamos el archivo Javascript del componente, usualmente en el <head> del documento:
<script src="/components/AppElement.js"></script>

Una vez hecho esto, utilizamos el componente (custom element) donde se requiera, simplemente añadiendo nuestra etiqueta:

<app-element></app-element>

Como ven, rápido y sencillo. Sin complicaciones.

Cargar componente desde JS

Pero en algunas ocasiones, podríamos preferir cargar el WebComponent desde Javascript en lugar de HTML, ya que puede ser más versátil en ciertas situaciones. Por ejemplo, si tenemos un gran número de componentes quizás podemos preferir centralizar los imports en un fichero central de Javascript, que pueda ser reutilizado, en lugar de tener varias etiquetas <script> en tus archivos HTML. En ese caso, debemos hacer lo siguiente:

  1. Cargamos un archivo Javascript principal donde vamos a centralizarlo todo. Este puede estar en el raíz o en una carpeta js, dependiendo de nuestra arquitectura. En cualquier caso, será el equivalente al «main» de muchos lenguajes de programación:
<script type="module" src="/js/index.js"></script>

Es muy importante darse cuenta de que es obligatorio utilizar el atributo type establecido a module. Con esto le indicamos al navegador que lo que estamos cargando es un fichero donde vamos a utilizar módulos ES, o lo que es lo mismo, vamos a importar código desde ficheros externos utilizando la sentencia import.

Si se nos olvidara añadir el type="module" a nuestro script, probablemente en la consola Javascript nos aparecerá un error similar al siguiente:

Uncaught SyntaxError: Cannot use import statement outside a module

  1. Por su parte, en el fichero index.js tendremos que hacer las importaciones necesarias para cargar el componente y ponerlo a disposición de nuestra página web:
import "./components/AppElement.js";

Con esta modalidad de importación, simplemente indicamos a Javascript que incluya y procese el código que contiene dicho fichero Javascript, cargando el componente de una forma análoga a como lo hicimos en el apartado anterior, mediante HTML y una etiqueta <script>.

Utilizar un componente

Una vez tengamos nuestro componente cargado, existen 3 formas principales de consumirlo (utilizarlo) en nuestra página. La primera y más sencilla ya la hemos visto, simplemente escribimos el nombre de nuestro custom element en el HTML:

<app-element></app-element>

Esta es la forma más básica. Sin embargo, también podemos querer crear el componente desde Javascript, para poder hacerlo más dinámico y aprovecharnos de toda la potencia de Javascript.

En ese caso, tendríamos que hacer lo siguiente:

const appElement = document.createElement("app-element");
document.body.appendChild(appElement);

Hemos creado el elemento HTML <app-element> en memoria y lo insertamos en el DOM del documento HTML en la segunda línea, obteniendo un resultado análogo al método básico, pero pudiendo aprovechar las características de programación de Javascript, y por ejemplo, hacer una operación repetitiva en un bucle o que dependa de una variable.

Por último, una tercera forma también sería posible, en el caso de que, por alguna razón, quisieramos acceder a la clase en cuestión del componente. En nuestro fichero AppElement.js, tendríamos que exportar la clase, para poder importarla desde otro archivo:

export class AppElement extends HTMLElement {
  /* ... */
}

También se podría hacer una exportación por defecto, sin embargo, las exportaciones específicas suelen ser algo más flexibles. Ahora, desde nuestro archivo index.js, en lugar de hacer una importación como la que vimos más atrás, la haríamos de esta forma:

import { AppElement } from "./components/AppElement.js";

const appElement = new AppElement();
document.body.appendChild(appElement);

Obsérvese que en el fichero index.js hemos importado la clase AppElement que exportamos en el punto anterior. En el resto del código del fichero podríamos ahora trabajar con ella de forma análoga a como lo hicimos más atrás con .createElement().

Manz
Publicado por Manz

Docente, divulgador informático y freelance. Autor de Emezeta.com, es profesor en la Universidad de La Laguna y dirige el curso de Programación web FullStack y Diseño web FrontEnd de EOI en Tenerife (Canarias). En sus ratos libres, busca GIF de gatos en Internet.