Si desea mejorar la calidad general de su código, es posible que desee mantener sus modelos de datos claramente desacoplados de las vistas subyacentes.
Los marcos funcional-reactivos o bibliotecas de interfaz de usuario como Rimmel.js, que tienen soporte completo para Observables, le permiten definir sus modelos como flujos observables (por ejemplo: flujos simples de entrada y salida de datos), además de un diseño poco conocido. patrón que es el adaptador de eventos.
Los adaptadores de eventos lo ayudan a asignar cualquier evento de origen (por ejemplo: MouseEvent, PointerEvent, KeyboardEvent, etc. del DOM) al formato realmente utilizado por sus modelos de datos, de modo que se liberen de esta tarea de conversión y, en última instancia, se desacoplen del Interfaz de usuario.
Rimmel simplifica la conexión de dicha transmisión al DOM:
import { rml } from 'rimmel'; const component = () => { const total = new Subject().pipe( map(x => doSomethingWith(x)), ); return rml`${stream}`; }
La vinculación es trivial: Rimmel conecta los eventos de clic provenientes del botón directamente a su flujo observable, que recibirá instancias de PointerEvent cada vez que se haga clic en el botón.
Hasta ahora, todo bien. ¿Qué pasa si tu transmisión necesita tomar datos de múltiples fuentes y comportarse de manera diferente dependiendo de cada una?
Creemos un contador simple con un botón de incremento y uno de decremento, cada uno sumando o restando uno.
import { scan } from 'rxjs'; import { rml } from 'rimmel'; const component = () => { const total = new BehaviorSubject(0).pipe( scan((old, new) => old new, 0), ); return rml`${total}`; }
Esto funciona, pero la parte de la plantilla incluye algo de lógica, que es un antipatrón. Idealmente, deberíamos esforzarnos por tener plantillas sin lógica para maximizar la capacidad de prueba en general.
Entonces, con Rimmel 1.2 tienes una nueva característica, Event Mappers, que ayuda exactamente con eso. Le ayudan a asignar eventos DOM a lo que su modelo necesita, para que pueda mantener la lógica perfectamente separada de la plantilla. Así es como funciona.
import { map, scan } from 'rxjs'; import { rml, reversePipe } from 'rimmel'; const Inc = reversePipe(map(() => 1)); const Dec = reversePipe(map(() => -1)); const component = () => { const total = new BehaviorSubject(0).pipe( scan((old, new) => old new, 0), ); return rml`${total}`; };
reversePipe es la adición innovadora aquí: una herramienta de creación de canalizaciones que funciona de manera opuesta a la función pipe() en RxJS. Mientras que este último aplica transformaciones a la salida de una secuencia, ReversePipe() las aplica en la entrada.
De esta manera, se asegura de que su flujo principal Asunto/BehaviorSubject/Observer/EventListener siempre obtenga datos en los formatos que desea y mantenga su adaptador como una preocupación separada.
Puede utilizar cualquier operador RxJS en sus canalizaciones inversas. ¿Solo desea filtrar ciertos eventos, como cuando el usuario presiona Enter, en lugar de cualquier otra tecla? Simplemente use el operador de filtro:
import { Subject, filter, map } from 'rxjs'; import { rml, inputPipe } from 'rimmel'; const UpperOnEnter = inputPipe( filter((e: Event) => e.key == 'Enter'), map((e: Event) => e.target.value.toUpperCase()), ); const Component = () => { const state = new Subject(); return rml` Type some text and hit Enter${state}`; };
Con respecto a las pruebas unitarias, esta es una pequeña pero útil adición que hará que las pruebas sean más simples y eficientes.
Echa un vistazo a los mapeadores de eventos en acción en este Stackblitz
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3