Si vous souhaitez améliorer la qualité globale de votre code, vous souhaiterez peut-être garder vos modèles de données parfaitement découplés des vues sous-jacentes.
Les frameworks fonctionnels-réactifs ou les bibliothèques d'interface utilisateur comme Rimmel.js, qui prennent entièrement en charge les observables, vous permettent de définir vos modèles comme des flux observables (par exemple : flux de données simples entrants, flux de données sortants) en plus d'une conception peu connue. modèle qui est l'adaptateur d'événement.
Les adaptateurs d'événements vous aident à mapper tous les événements sources (par exemple : MouseEvent, PointerEvent, KeyboardEvent, etc. du DOM) au format réellement utilisé par vos modèles de données, afin qu'ils soient libérés de cette tâche de conversion et soient finalement découplés du Interface utilisateur.
Rimmel simplifie la connexion d'un tel flux au DOM :
import { rml } from 'rimmel'; const component = () => { const total = new Subject().pipe( map(x => doSomethingWith(x)), ); return rml` <button onclick="${stream}">click me</button> <div id="display">${stream}</div> `; }
La liaison est triviale : Rimmel connecte les événements de clic provenant du bouton directement dans votre flux observable, qui recevra des instances de PointerEvent à chaque fois que vous cliquez sur le bouton.
Jusqu’ici tout va bien. Que se passe-t-il si votre flux doit extraire des données de plusieurs sources et se comporter différemment en fonction de chacune ?
Créons un compteur simple avec un bouton d'incrémentation et un bouton de décrémentation, chacun en ajoutant ou en soustrayant un.
import { scan } from 'rxjs'; import { rml } from 'rimmel'; const component = () => { const total = new BehaviorSubject(0).pipe( scan((old, new) => old+new, 0), ); return rml` <button onclick="${() => total.next(1)}">inc</button> <button onclick="${() => total.next(-1)}">dec</button> <div>${total}</div> `; }
Cela fonctionne, mais la partie modèle inclut une certaine logique, qui est un anti-modèle. Idéalement, nous devrions nous efforcer d'avoir des modèles sans logique pour maximiser la testabilité globale.
Donc, avec Rimmel 1.2, vous disposez d'une nouvelle fonctionnalité, Event Mappers, qui aide exactement à cela. Ils vous aident à mapper les événements DOM en fonction des besoins de votre modèle, afin que vous puissiez garder la logique parfaitement séparée du modèle. Voici comment cela fonctionne.
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` <button onclick="${Inc(total)}">inc</button> <button onclick="${Dec(total)}">dec</button> <div>${total}</div> `; };
reversePipe est l'ajout innovant ici : un outil de création de pipeline qui fonctionne à l'opposé de la fonction pipe() dans RxJS. Alors que ce dernier applique des transformations à la sortie d'un flux, reversePipe() les applique à l'entrée.
De cette façon, vous êtes sûr que votre flux principal Subject/BehaviorSubject/Observer/EventListener obtient toujours les données dans les formats souhaités et vous conservez votre adaptateur comme une préoccupation distincte.
Vous pouvez utiliser n'importe quel opérateur RxJS dans vos pipelines inverses. Souhaitez-vous filtrer uniquement certains événements, comme lorsque l'utilisateur appuie sur Entrée, plutôt que sur toute autre touche ? Utilisez simplement l'opérateur de filtre :
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<br> <input onkeydown="${UpperOnEnter(state)}"> <div>${state}</div> `; };
En ce qui concerne les tests unitaires, il s'agit d'un ajout petit mais utile qui rendra les tests plus simples et plus efficaces.
Découvrez les mappeurs d'événements en action sur ce Stackblitz
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!