Lección 16: Componentes | Curso JavaScript

Lección 16: Componentes

Es común, cuando desarrollamos un App o sitio web, encontrarnos con repeticiones de bloques HTML cuyas funcionalidades son clónica. Para simplificar el desarrollo, y centralizar la lógica, se tiende a crear componentes. Un técnica de arquitectura donde divides las funcionalidades en fragmentos reutilizables formado por la triada de HTML, CSS y JavaScript.

Con la llegada de los módulos, que hemos aprendido en la lección anterior, nos permite crear componentes nativamente (Vainilla) sin recurrir a frameworks externos como ReactJS, VueJS o Angular. Se denomina Custom Elements.

Custom Elements o Componentes personalizados

A partir de la siguiente etiqueta que he inventado, con un atributo para indicar la cifra, puedo formatear un precio con un doble decimal y el símbolo del euro.

<price-component amount="34.2"></price-component>

34.20 €

¿Cómo es posible? En JavaScript solo necesito crear una clase que herede de HTMLElement y registrarlo con customElements.

// Clase del componente
class PriceComponent extends HTMLElement {

    constructor() {
        super();
        this.textContent = `${parseFloat(this.getAttribute("cantidad")).toFixed(2)} €`;
    }

}

// Al registrar definimos el nombre del componente, que siempre debe estar formado por dos palabras como mínimo.
customElements.define("price-component", PriceComponent);

Puedes crear todos los que haga uso tu sitio para todo tipo de funcionalidades: filtrado, formateo, cálculos, conexiones asíncronas… Aunque estamos limitados a la hora de incluir HTML. Para ello incluiremos una plantilla HTML.

Componentes personalizados con plantilla HTML

En el siguiente ejemplo puedes ver como se ha declarado un componente con el objetivo de representar algunas fichas de personales históricos. Son totalmente configurables a partir de sus atributos y hacen uso de una plantilla para definir la estructura HTML.

<card-component
    name="Lope de Vega"
    country="Spain"
    avatar="https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Lope_de_vega.JPG/640px-Lope_de_vega.JPG"
></card-component>

<card-component
    name="Francisco de Quevedo "
    country="Spain"
    avatar="https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Retrato_de_Francisco_de_Quevedo%2C_after_an_original_attributed_to_John_Vanderham.jpg/640px-Retrato_de_Francisco_de_Quevedo%2C_after_an_original_attributed_to_John_Vanderham.jpg"
></card-component>

<template id="card">
    <div>
        <article class="card">
            <header>
                <h2 class="card__name"></h2>
                <h3 class="card__country"></h3>
            </header>
            <p>
                <img class="card__avatar" src="" alt="Avatar">
            </p>
        </article>
    </div>
</template>

Escritores en escritores

La única diferencia es que en el momento de renderizar capturaremos el contenido de la plantilla e iremos modificando las etiquetas que nos haga falta.

class CardComponent extends HTMLElement {

    constructor() {
        super();
        this.render();
    }

    render() {
         // Obtenemos el contenido de la plantilla
         const template = document.querySelector("template#card").content.firstElementChild;
         const miTemplate = template.cloneNode(true);
         // Modificamos el HTML de la plantilla
         miTemplate.querySelector(".card__name").textContent = this.getAttribute("name");
         miTemplate.querySelector(".card__country").textContent = this.getAttribute("country");
         miTemplate
             .querySelector(".card__avatar")
             .setAttribute("src", this.getAttribute("avatar"));
         // Insertamos el HTML modificado
         this.appendChild(miTemplate);
    }
}

customElements.define("card-component", CardComponent);

Sobre la base que hemos definido, ya podemos construir componentes a medida todo lo complejo que se nos pase por la cabeza.

Si no quieres depender de una <template>, y que tu componente pueda ser llamado en todas la páginas, debes introducir el HTML dentro de tu JavaScript.

A continuación puedes ver una adaptación del código anterior.

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8"/>
         <title>Ejemplo reutilizable</title>
    </head>
    <body>
        <card-component
            name="Lope de Vega"
            country="Spain"
            avatar="https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Lope_de_vega.JPG/640px-Lope_de_vega.JPG"
        ></card-component>

        <card-component
            name="Francisco de Quevedo"
            country="Spain"
            avatar="https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Retrato_de_Francisco_de_Quevedo%2C_after_an_original_attributed_to_John_Vanderham.jpg/640px-Retrato_de_Francisco_de_Quevedo%2C_after_an_original_attributed_to_John_Vanderham.jpg"
        ></card-component>


    <script>
/**
 * Example usage:
 *
 * <card-component
 *     name="Francisco de Quevedo"
 *     country="Spain"
 *     avatar="https://upload.wikimedia.org...original_attributed_to_John_Vanderham.jpg"
 *     ></card-component>
 */

class CardComponent extends HTMLElement {

    constructor() {
        super();
        // Get params
        const name = this.getAttribute("name");
        const country = this.getAttribute("country");
        const avatar = this.getAttribute("avatar");
        // Set HTML
        this.innerHTML = `
            <article class="card">
                <header>
                    <h2 class="card__name">${name}</h2>
                    <p class="card__country">${country}</p>
                </header>
                <p>
                    <img class="card__avatar" src="${avatar}" alt="Avatar">
                </p>
            </article>
        `;
    }
}

customElements.define("card-component", CardComponent);
    </script>
    </body>
</html>

Mucho más limpio. ¿Verdad? La única pega es que el diseñador web debe modificar el HTML desde el JavaScript ya que no puede acceder a la etiqueta <template>. Ahora bien, si el componente es muy complejo, es mejor que se encargue el desarrollador bajo su supervisión.

Actividad 1

Crea un componente personalizado que limite un texto, por muy largo que sea, a 5 palabras. Debe terminar con tres puntos (...).

Actividad 2

Crea un componente que muestre una imagen aleatoria. Si quieres darle más personalizacion, permite que se pueda incluir un atributo con la temática de la imagen.

Actividad 3

Crea un componente para ver el avatar de un usuario de GitHub. Debe permitir incluir el nombre de usuario y el tamaño del avatar.

Ayudate del siguiente url: https://github.com/{usuario}.png.

Esta obra está bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivadas 4.0 Internacional.

Atribución/Reconocimiento-NoComercial-SinDerivados 4.0 Internacional

¿Me ayudas?

Comprame un café
Pulsa sobre la imagen

No te sientas obligado a realizar una donación, pero cada aportación mantiene el sitio en activo logrando que continúe existiendo y sea accesible para otras personas. Además me motiva a crear nuevo contenido.

Comentarios

{{ comments.length }} comentarios

Nuevo comentario

Nueva replica  {{ formatEllipsisAuthor(replyComment.author) }}

Acepto la política de Protección de Datos.

Escribe el primer comentario