HTML en Webcomponents

Cómo escribir código HTML en un WebComponent nativo


En los artículos anteriores hemos visto los primeros pasos para saber que es un WebComponent, como crear su base, estructurar sus carpetas y archivos, y crear nuestra primera etiqueta HTML propia. Sin embargo, lo más probable es que aún no hayamos visto todo su potencial, ya que no hemos hecho ningún ejemplo práctico.

¿Por qué HTML desde un componente?

Antes de pasar a crear componentes reales, recordemos que nos interesa gestionar el HTML desde nuestro componente. Esto es importante porque queremos no tener que repetir código HTML en nuestra página una y otra vez, sino escribirlo de forma genérica en un componente, y utilizar el componente cada vez que lo necesitemos.

<!-- En lugar de escribir esto... -->
<div class="card">
  <h1>ManzDev</h1>
  <img src="manzdev.png" alt="Avatar de ManzDev">
  ...
</div>

<div class="card">
  <h1>ikurotime</h1>
  <img src="ikurotime.png" alt="Avatar de ikurotime">
  ...
</div>

<!-- Queremos escribir esto... -->
<user-card name="ManzDev"></user-card>
<user-card name="ikurotime"></user-card>

Al simplificar todo en el componente <user-card>, quedará mucho más organizado, legible y estructurado, haciendo mucho más fácil los cambios y modificaciones, ganando en mantenibilidad.

Observa que los componentes dependen de un dato, en nuestro ejemplo el nombre del usuario. Esto lo veremos más adelante, gestionándolo mediante los atributos de una etiqueta HTML.

Formas de escribir HTML

Obviamente, el código HTML tendrá que escribirse en nuestro componente, que es un archivo Javascript ubicado en la carpeta components/. Hay varias formas de hacerlo, entre las que se encuentras las siguientes:

  • 1️⃣ Escribir el código HTML mediante un
  • 2️⃣ Escribir el código HTML mediante métodos del DOM
  • 3️⃣ Escribir el código HTML mediante plantillas (ver más adelante)
  • 4️⃣ Escribir el código HTML mediante librerías (ver más adelante)

En este artículo vamos a centrarnos en las dos primeras, y en el próximo veremos las dos siguientes.

HTML a través de strings

Probablemente, la forma más rápida de escribir HTML en nuestro componente es añadir el código HTML en un y luego insertarlo en el componente. Para ello, tenemos varias propiedades para trabajar con el DOM de forma rápida, atómica y bastante cómoda para el desarrollador.

Dichas propiedades son las siguientes:

Propiedad Descripción
this.innerHTML Reemplaza o añade código HTML al componente.
this.outerHTML Idem al anterior, pero también reemplaza el propio componente. Poco usado en WebComponents.
this.textContent Reemplaza el contenido de texto del componente. No renderiza HTML.
this.innerText Similar al anterior, pero tiene en cuenta textos ocultos. Menos eficiente.

Las dos primeras propiedades, .innerHTML y .outerHTML se utilizan para reemplazar el marcado HTML de un componente, aunque .outerHTML no es demasiado práctico en los componentes, puesto que también sustituye la propia etiqueta del componente. Por otro lado, las dos últimas propiedades se utilizan para obtener solo el contenido textual, pero en general utilizaremos .textContent, ya que es algo más eficiente que .innerText.

Más información en Insertar elementos en el DOM

De las anteriores, utilizaremos .innerHTML para escribir código HTML y renderizarlo en nuestro componente. Veamos un ejemplo usándolo en nuestro componente:

class AppElement extends HTMLElement {
  constructor() {
    super();
    this.innerHTML = "<div>ManzDev</div>";
  }
}

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

Uno de los principales problemas que podemos tener aquí es que añadir código HTML en un es incómodo y tiene algunas desventajas como que el HTML no tiene resaltado de sintaxis de color o que se hace difícil de leer todo en una línea.

Para corregir esto, vamos a instalar la extensión ES6-strings-html de VSCode y a escribir el comentario /* html */ justo antes del . Esta extensión también permite resaltar sintaxis de otros fragmentos de código como CSS, SVG, SQL, XML o GLSL (OpenGL Shading).

Además, acostúmbrate a utilizar las comillas ``, también llamadas string templates. Este tipo de comillas nos permite que el código HTML más complejo se lea mucho mejor, pudiendo insertar nuevas líneas, utilizar ${} para agrupar las expresiones o variables JS, etc.

class AppElement extends HTMLElement {
  constructor() {
    super();
    this.innerHTML = /* html */`
      <div class="card">
        <h1>ManzDev</h1>
      </div>`;
  }
}

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

Esta forma de incluir marcado HTML dentro de strings está muy sujeta a controversia y no gusta a todos los desarrolladores. En ciertas comunidades como las de CSS-in-JS o React es muy utilizada (con considerables diferencias), pero en otras suele causar rechazo. Sin embargo, se ha convertido en la forma más extendida al no requerir archivos externos. Si no te gusta, no te preocupes, iremos viendo otras alternativas para escribir HTML.

Por defecto, en el interior de un no nos funcionará el autocompletado de etiquetas. Sin embargo, puedes activar EMMET en el interior de string templates, te lo explico más adelante, en EMMET en String templates.

HTML a través del DOM

Otra forma de manejar el marcado HTML del componente es a través de la API del DOM de Javascript. En principio es un poco más verboso y puede resultar tedioso, pero ofrece mejor rendimiento y puede ser muy interesante si somos organizados.

Algunos de los métodos que nos puede interesar usar:

Método Descripción
document.createElement(tag) Crea y devuelve una etiqueta HTML tag.
container.append( element) Añade el elemento element dentro de container.
container.insertAdjacentHTML(pos,html) Inserta el código html en container.
container.insertAdjacentElement(pos,element) Inserta el elemento element en container.
  • 1️⃣ .createElement() crea el elemento HTML pasado por parámetro y lo devuelve, generalmente para almacenarlo en una variable. Es importante recalcar que ese elemento no se guarda en el documento HTML, aunque se haga sobre document.

  • 2️⃣ Para guardarlo en el documento HTML, hay que utilizar uno de los siguientes métodos de la tabla, que son los que realmente los añaden al DOM (documento HTML).

Veamos un ejemplo para hacer lo mismo que el código del apartado anterior, pero utilizando los métodos del DOM:

class AppElement extends HTMLElement {
  constructor() {
    super();
    const card = document.createElement("div");
    card.classList.add("card");
    this.append(card);

    const heading = document.createElement("h1");
    heading.textContent = "ManzDev";
    card.append(heading);
  }
}

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

Como vemos, el código es algo más «verboso», pero puede ser realmente útil cuando queremos realizar bucles o una lógica dinámica que es más compleja de crear al estilo del apartado anterior, mediante cadenas de texto .

Por otro lado, los métodos .insertAdjacentHTML() o .insertAdjacentElement() son un híbrido entre las formas de manipulación del DOM que hemos visto hasta ahora, donde tenemos más flexibilidad a la hora de insertar, ya que el parámetro pos es un que puede determinar el punto exacto donde se añadirá el elemento.

append() vs insertAdjacentHTML()

► Tienes más información de su funcionamiento en Insertar elementos en el DOM.

EMMET en String templates

Es muy posible que queramos utilizar la posibilidad de utilizar EMMET en los strings templates al igual que lo hacemos en un documento HTML, de forma que al escribir p y pulsar TAB, nos lo reemplace por <p></p> y posicione el cursor en su interior.

En Visual Studio Code es muy sencillo. Basta con pulsar F1 y buscar la opción Open User Settings (JSON). Nos aparece un fichero .json con la configuración actual del usuario. Buscaremos o añadiremos la siguiente línea:

{
  [...],
  "emmet.includeLanguages": {
    "javascript": "html"
  },
  [...]
}

Esto hará que EMMET pueda ser escrito en ficheros Javascript, algo que junto a la extensión de VSCode mencionada anteriormente, hará que escribir código HTML en WebComponents sea más sencillo y cómodo.

¿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