Búsqueda de sitios web

typescript - ¿Cómo puedo obtener el cambio de estado de un componente en otro componente con litElement?


Comencé un proyecto basado en LitElement. Hay muchos componentes anidados entre sí. Digamos que tenemos esta estructura:

el componente raíz es my-app

import { LitElement, html, customElement, query } from 'lit-element';
import './my-form';
import './my-view';
import { MyView } from './my-view';

@customElement('my-app')
export class MyApp extends LitElement {
  @query('my-view') private myView?: MyView;

  private handleCountChange(e: CustomEvent<{ count: number }>) {
    if (!this.myView) throw 'my-view not found!';
    this.myView.count = e.detail.count;
  }

  render() {
    return html`
      <my-form @countChanged=${this.handleCountChange}></my-form>
      <my-view></my-view>
    `;
  }
}

como ves, tenemos dos componentes: my-form

import { LitElement, html, customElement, property } from 'lit-element';

@customElement('my-form')
export class MyForm extends LitElement {
  @property({ type: Number }) count: any = 0;

  private updateCount(e: KeyboardEvent) {
    this.count = (<HTMLInputElement>e.target).value;
    this.dispatchEvent(
      new CustomEvent('countChanged', {
        composed: true,
        bubbles: true,
        cancelable: true,
        detail: { count: this.count }
      })
    );
  }

  render() {
    return html`
      <input value=${this.count} @input=${this.updateCount} type="text" />
    `;
  }
}

y mi opinión:

import { LitElement, html, customElement, property } from 'lit-element';

@customElement('my-view')
export class MyView extends LitElement {
  @property({ type: Number }) count: number = 0;

  render() {
    return html`
      <p>${this.count}</p>
    `;
  }
}

Para pasar los cambios de la propiedad count desde my-form a my-view, despaché un listener de eventos y luego lo usé en my-app. Después, en handleCountChange, estoy asignando el valor de count a MyView, que se importa como una clase además de importarlo como un componente.

Actualmente, esto funciona, pero siento que es un camino largo, especialmente cuando tengo más componentes anidados. Me gustaría saber si hay una mejor manera de hacer eso. ¿Existe algo similar a Context API que existe en react.js? Pensé en usar redux, pero alguien no lo recomendó con litElement. Una de las ideas en las que estoy pensando es despachar el evento al document en lugar del componente actual, ¡pero tal vez esto sea una mala práctica! ¿Cuáles son sus sugerencias? Por favor, háganmelo saber.

Respuesta #1

Probablemente ya hayas resuelto este problema, pero puedo enviarte cómo lo manejaría.

Necesitas elevar tu estado hasta tu componente my-app. Este estado será una única fuente de verdad y entregará el valor count a los componentes hijos my-form y my-view.

En el componente my-app, puedes cambiar handleCountChange a algo así (en caso de que definas count como un atributo y permitas que my-app reciba el valor inicial desde los atributos):

 private handleCountChange(e: CustomEvent<{ count: number }>) {
   this.setAttribute('count', count); // If you set `count` as observed attribute, you will not need to call `requestUpdate` method
 }

o así, si defines count como propiedad de la clase

 private handleCountChange(e: CustomEvent<{ count: number }>) {
   this.count = count;
   this.requestUpdate(); // force to call render method which is necessary in this case
 }

Tenga en cuenta que también tendrá que enviar el valor de count al componente my-form. También funcionará sin hacerlo, pero si lo hace, perderá una única fuente de verdad de su estado y eso puede causar un comportamiento inesperado potencial.

Si necesitará enviar un ejemplo, por favor avíseme.