Se você deseja melhorar a qualidade geral do seu código, você pode querer manter seus modelos de dados bem dissociados das visualizações subjacentes.
Estruturas funcionais-reativas ou bibliotecas de UI como Rimmel.js, que têm suporte total para Observáveis, permitem que você defina seus modelos como fluxos observáveis (por exemplo: fluxos simples de entrada e saída de dados), além de um design pouco conhecido padrão que é o adaptador de eventos.
Os adaptadores de eventos ajudam a mapear quaisquer eventos de origem (por exemplo: MouseEvent, PointerEvent, KeyboardEvent do DOM, etc.) para o formato realmente usado por seus modelos de dados, para que eles sejam liberados dessa tarefa de conversão e, em última análise, desacoplados do IU.
Rimmel simplifica a conexão de tal fluxo ao DOM:
import { rml } from 'rimmel'; const component = () => { const total = new Subject().pipe( map(x => doSomethingWith(x)), ); return rml`${stream}`; }
A ligação é trivial: Rimmel conecta eventos de clique provenientes do botão diretamente em seu fluxo observável, que receberá instâncias de PointerEvent toda vez que o botão for clicado.
Até agora tudo bem. E se o seu stream precisar coletar dados de várias fontes e se comportar de maneira diferente dependendo de cada uma?
Vamos criar um contador simples com um botão de incremento e um botão de decremento, cada um adicionando ou subtraindo um dele.
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}`; }
Isso funciona, mas a parte do modelo inclui alguma lógica, que é um antipadrão. Idealmente, deveríamos nos esforçar para ter modelos sem lógica para maximizar a testabilidade geral.
Então, com o Rimmel 1.2 você tem um novo recurso, Event Mappers, que ajuda exatamente nisso. Eles ajudam você a mapear eventos DOM de acordo com as necessidades do seu modelo, para que você possa manter a lógica perfeitamente separada do modelo. Veja 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 é a adição inovadora aqui: uma ferramenta de criação de pipeline que funciona de forma oposta à função pipe() no RxJS. Enquanto o último aplica transformações à saída de um fluxo, reversePipe() as aplica na entrada.
Dessa forma, você tem certeza de que seu fluxo principal Subject/BehaviorSubject/Observer/EventListener sempre obtém dados nos formatos desejados e mantém seu adaptador como uma preocupação separada.
Você pode usar qualquer operador RxJS em seus pipelines reversos. Você deseja filtrar apenas determinados eventos, como quando o usuário pressiona Enter, em vez de qualquer outra tecla? Basta usar o 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}`; };
No que diz respeito aos testes unitários, esta é uma adição pequena, mas útil, que tornará os testes mais simples e eficientes.
Confira os mapeadores de eventos em ação neste Stackblitz
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3