> Manuales > Manual de Lit

Cómo realizar cambios en las propiedades del componente como respuesta a eventos producidos por el usuario. Veremos cómo declarar eventos en el template y cómo cambiando propiedades se actualizan automáticamente los templates de Lit.

Cambiar propiedades como respuesta a eventos en Lit

Vamos a comenzar un nuevo componente para avanzar un poco más sobre las bases del desarrollo de custom elements con Lit. La idea es aprender de manera rápida cómo se asocian manejadores de eventos declarativamente, por medio de los templates. No será una descripción completa sobre todos los detalles relacionados con la gestión de eventos, pero sí una introducción, que nos permitirá apreciar también cómo los componentes se comportan de manera reactiva.

El ejemplo será super sencillo y no muy imaginativo, porque vamos a crear el típico contador con el que empiezan muchos tutoriales de frameworks en general. Consiste en un contenedor que muestra un número y dos botones, para añadir y sustraer una unidad de ese número.

Creamos una propiedad numérica

Vamos a comenzar creando una propiedad en el componente, que será de tipo Number, como has podido imaginar.

static properties = {
    counter: { type: Number },
}

Esta propiedad la podemos inicializar, para ello usamos el constructor como vimos en el artículo anterior dedicado a las propiedades en Lit.

constructor() {
    super();
    this.counter = 0;
}

En el artículo anterior ya explicamos las bases del trabajo con propiedades del componente.

Crear un template que muestre el número

Vamos a crear ahora una vista para el componente que muestre el número del contador, donde colocaremos además dos botones para aumentar y disminuir esa cuenta.

render() {
    return html`
        <div class="count">${this.counter}</div>
        <button>+1</button>
        <button>-1</button>
    `;
}

Ahora, si lo deseas, puedes aplicar algo de estilo a este componente, tal como aprendimos en el artículo de los primeros pasos con Lit. Por ejemplo podríamos usar este CSS.

static styles = css`
    :host {
        display: block;
    }
    .count {
        display: inline-block;
        font-size: 2rem;
        border-radius: 1rem;
        padding: 0.7rem 1rem;
        background-color: #236bf0;
        color: #fff;
        font-weight: bold;
    }
`;

Declarar manejadores de eventos en un template

Ahora vamos a definir declarativamente los manejadores de eventos necesarios para que, cuando se pulsen los botones de incrementar o decrementar el contador, se cambie la propiedad counter del componente.

Para definir eventos clic en los templates usamos la notación @click, asignando el método del componente que va a hacer las veces de manejador.

Puedes ver cómo quedaría en este código donde hemos actualizado el template para asignar ambos manejadores.

render() {
    return html`
        <div class="count">${this.counter}</div>
        <button @click=${this.add}>+1</button>
        <button @click=${this.subtract}>-1</button>
    `;
}

Es importante que veas que al declarar los manejadores de eventos en el template no colocamos los paréntesis al método @click=${this.add}. Es decir, this.add no lleva paréntesis después. Si pusieras paréntesis estarías invocando la función al procesarse el template y en este caso no queremos que se invoque la función hasta que se hace clic sobre el botón.

Por supuesto, ahora necesitamos definir los correspondientes métodos add() y subtract(), que se encargarán de actualizar el valor de la propiedad "counter".

add() {
    this.counter++;
}

subtract() {
    this.counter--;
}

El template es reactivo

¡Los métodos no pueden ser más simples! la única acción que realizan es cambiar el valor de la propiedad. Todo el flujo de actualización de la vista del componente lo realiza Lit.

Simplemente, al cambiar el valor de la propiedad se hace un refresco del template, actualizando el lugar donde se está usando esa propiedad. Esto lo hace además de manera muy optimizada, ya que Lit es capaz de saber los lugares donde está usándose esa propiedad y cambiar simplemente el lugar donde se necesita.

En las pruebas de benchmark publicadas se ha demostrado que Lit consigue mayor rendimiento que React con su técnica basada en Virtual DOM. Lit no requiere Virtual DOM por lo que también requiere menor uso de memoria. De todos modos, reconocemos que no hay que enloquecer por las pruebas de rendimiento y sí por la experiencia de desarrollo y la calidad del código que nos proporciona el desarrollo basado en componentes, ya sea React, Lit, Vue, Angular o lo que estés usando.

Más adelante podemos hablar sobre nociones interesantes que podemos saber sobre cuándo y cómo se actualizan los templates. El objetivo ahora era simplemente ver cómo Lit hace su trabajo y actualiza el template automáticamente cuando cambian los valores de las propiedades.

Código del componente completo

Para acabar vamos a ver el código completo del componente que acabamos de crear.

import {LitElement, html, css} from 'lit';

class DwCounter extends LitElement {

    static styles = css`
        :host {
            display: block;
        }
        .count {
            display: inline-block;
            font-size: 2rem;
            border-radius: 1rem;
            padding: 0.7rem 1rem;
            background-color: #236bf0;
            color: #fff;
            font-weight: bold;
        }
    `;

    static properties = {
        counter: { type: Number },
    }

    constructor() {
        super();
        this.counter = 0;
    }

    render() {
        return html`
            <div class="count">${this.counter}</div>
            <button @click="${this.add}">+1</button>
            <button @click="${this.subtract}">-1</button>
        `;
    }

    add() {
        this.counter++;
    }

    subtract() {
        this.counter--;
    }
}

customElements.define('dw-counter', DwCounter);

Por cierto, este código lo meteremos en un archivo llamado dw-counter.js que colocaremos en la carpeta "components", siguiendo con la arquitectura del proyecto propuesta en el artículo de los primeros pasos.

Usar el componente

En capítulos anteriores del Manual de Lit ya hemos visto cómo se usan los componentes. No es algo que explicaremos en todos los artículos, porque en determinado momento lo vamos a dar por sabido. No obstante, como estamos solamente empezando, lo veremos de nuevo paso a paso. En resumen, para poder usar este componente hay que hacer un par de pasos:

Importar el componente en el index.js

Ahora nuestro index.js tendrá este código, en el que se realizan los imports de los dos componentes que hemos realizado hasta el momento.

import './components/dw-message.js';
import './components/dw-counter.js';

Usar el componente en el HTML

El componente lo podemos usar colocando simplemente su etiqueta en el código HTML del archivo index.html.

<dw-counter></dw-counter>

Además, gracias a Lit, el atributo "counter" del componente puede servirnos para definir un valor inicial para el contador, de modo que no empiece en cero, tal como se había programado en el constructor.

<dw-counter counter="1"></dw-counter>

Como ya comentamos, la sincronización entre atributos y propiedades también corre por cuenta de Lit.

Para ver el código tal como lo hemos dejado hasta este artículo puedes entrar en este enlace de GitHub.

Conclusión

De momento eso es todo. Este artículo ha sido muy sencillo pero nos ha ofrecido un conocimiento esencial para crear componentes interactivos, mediante la declaración de manejadores de eventos. Lo hemos hecho de manera declarativa en el template, pero por supuesto puedes hacerlo de manera imperativa mediante Javascript nativo (addEventListener), ya que en el fondo todo esto es Javascript.

Ahora podemos responder con acciones dentro del componente cuando se producen clics sobre los elementos del template, lo que nos permitirá crear enseguida nuevos componentes para ir aprendiendo nuevas características de la librería Lit.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual