Heim  >  Artikel  >  Web-Frontend  >  Der Signal Store von NGRX – Aufschlüsselung der Hauptkonzepte

Der Signal Store von NGRX – Aufschlüsselung der Hauptkonzepte

WBOY
WBOYOriginal
2024-07-23 15:00:551183Durchsuche

The Signal Store from NGRX - breakdown of the main concepts

Eigenschaften

  • signalbasiert
  • funktional und deklarativ
  • wird für die lokale oder globale Zustandsverwaltung verwendet
  • erweiterbar mit benutzerdefinierten Funktionen

Wie ist der Vergleich mit dem NGRX Global Store?

  • Leichtere und vereinfachte API
  • Sie müssen sich nicht so viele Gedanken über den Datenfluss machen
  • scheint schwerer zu missbrauchen, etwa durch die Wiederverwendung von Aktionen
  • einfacher zu erweitern

Der Schöpfer von NGRX Signal Store, Marko Stanimirovic beschreibt hier NgRx SignalStore: Detaillierter Blick auf signalbasiertes Zustandsmanagement in Angular

Einschränkungen der klassenbasierten Zustandsverwaltung:

  • Typisierung: Es ist nicht möglich, dynamische Klasseneigenschaften oder Methoden zu definieren, die stark typisiert sind
  • Baumschütteln: Nicht verwendete Klassenmethoden werden nicht aus dem endgültigen Paket entfernt
  • Erweiterbarkeit: Mehrfachvererbung wird nicht unterstützt.
  • Modularität: Die Aufteilung von Selektoren, Updatern und Effekten in verschiedene Klassen ist möglich, aber nicht standardmäßig vorgesehen

Lassen Sie uns die API des Shops anhand von Codebeispielen erkunden. Wir verwenden ein Projekt mit einer Liste von Produkt- und Filterfunktionen.

Erstellen eines SignalStore

  • signalStore-Funktion, die einen injizierbaren Dienst zurückgibt, der zur Injektion geeignet ist und dort bereitgestellt wird, wo er verwendet werden muss.
import { signalStore } from "@ngrx/signals";

export const ProductStore = signalStore( … );

Bereitstellung von State withState

Wie bisher bei jedem NGRX-Store gibt es einen Anfangszustand, der bereitgestellt werden kann, indem die Funktion withState verwendet wird, die Objektliterale, Datensätze oder Factory-Funktionen (zum Erstellen eines dynamischen Anfangszustands) als Eingaben akzeptiert.

import { signalStore, withState } from "@ngrx/signals";

const initialProductState: ProductState = { products: [] };

export const ProductStore = signalStore(
 withState(initialProductState);
);

Berechneter Zustand withComputed

  • aufbaut auf der berechneten Funktion, um abgeleitete Zustände (berechnete Zustände) aus dem Speicher zu erstellen
import { signalStore, withComputed, withState } from "@ngrx/signals";

export const ProductStore = signalStore(
 withState(initialProductState),
 withComputed(({products}) => ({
   averagePrice: computed(() => {
     const total = products().reduce((acc, p) => acc + p.price, 0);
     return total / products().length;
   })
 })),

Durchführen von Operationen mit Methoden

  • Hier werden die Abläufe des Geschäfts definiert
  • Dies können Methoden sein, um den Store zu aktualisieren oder einige Vorgänge basierend auf seinem aktuellen Status auszuführen
import { signalStore, withComputed, withState, withMethods } from "@ngrx/signals";

export const ProductStore = signalStore(
 withState(initialProductState),
 withComputed(({products}) => ({
   averagePrice: computed(() => {
     const total = products().reduce((acc, p) => acc + p.price, 0);
     return total / products().length;
   })
 })),


 // CRUD operations
 withMethods((store,
   productService = inject(ProductService),
 ) => ({
   loadProducts: () => {
     const products = toSignal(productService.loadProducts())
     patchState(store, { products: products() })
   },
   addProduct: (product: Product) => {
     patchState(store, { products: [...store.products(), product] });
   },
   // ...
 })),

withMethods & withComputed Rufen Sie eine Factory-Funktion auf und geben Sie ein Wörterbuch mit Methoden und berechneten Signalen zurück, auf das mit zugegriffen werden kann der Laden. Sie laufen auch in einem Injektionskontext, der es ermöglicht, Abhängigkeiten in sie einzufügen.

Einhaken mitHaken

  • Lebenszyklusmethoden des Stores, derzeit verfügt er über die Methoden onInit und onDestroy
import { withHooks } from "@ngrx/signals"; 

export const ProductStore = signalStore(
 withHooks((store) => ({
   onInit() {
     // Load products when the store is initialized
     store.loadProducts();
   },
 })),
);

Verwalten von Sammlungen mit Entitäten

  • Verwenden Sie es, wenn Sie Daten wie „Produkte, Benutzer, Kunden usw.“ verwalten müssen, bei denen CRUD-Vorgänge für diese Funktion erforderlich sind
  • Es bietet eine Reihe von APIs zum Verwalten von Sammlungen, wie zum Beispiel: addEntity, setEntity, remoteEntity.
export const ProductStoreWithEntities = signalStore(
 withEntities<Product>(),


 // CRUD operations
 withMethods((store,
   productService = inject(ProductService),
 ) => ({
   loadProducts: () => {
     const products = toSignal(productService.loadProducts())();
     patchState(store, setAllEntities(products || []));
   },
   updateProduct: (product: Product) => {
     productService.updateProduct(product);
     patchState(store, setEntity(product));
   },

 })),

Es ist möglich, mehrere Funktionen hinzuzufügen, die mit „mit“ beginnen, aber sie können nur auf das zugreifen, was zuvor definiert wurde.

Erstellen benutzerdefinierter Funktionen mit signalStoreFeature

signalStoreFeature – wird zur Erweiterung der Funktionalität des Shops verwendet.

Stores können für große Unternehmensanwendungen komplex und schwer zu verwalten sein. Beim Schreiben von Features und Komponenten für ein Projekt gilt: Je besser und detaillierter die Aufteilung, desto einfacher ist es, den Code zu verwalten, zu pflegen und Tests dafür zu schreiben.

Angesichts der API, die SignalStore dem Store bereitstellt, kann es jedoch schwierig werden, sie zu verwalten, wenn der Code nicht entsprechend aufgeteilt wird. signalStoreFeature eignet sich zum Extrahieren spezifischer Funktionen eines Features (oder einer Komponente) in eine eigenständige testbare Funktion, die potenziell (und idealerweise) in anderen Stores wiederverwendet werden kann.

export const ProductStore = signalStore(
 // previous defined state and methods

 // Externalizing filtering options
 withFilteringOptions(),
);


export function withFilteringOptions() {
 return signalStoreFeature(
  // Filtering operations
 withMethods(() => ({
   getProductsBetweenPriceRange: (lowPrice: number, highPrice: number, products: Array<Product>, ) => {
     return products.filter(p => p.price >= lowPrice && p.price <= highPrice);
   },


   getProductsByCategory: (category: string, products: Array<Product>) => {
     return products.filter(p => p.category === category);
   },
 })),
 );
}

Nun ein Beispiel für signalStoreFeature, das die Möglichkeit zeigt, signalStoreFeature(s) über mehrere Geschäfte hinweg wiederzuverwenden.

import { patchState, signalStoreFeature, withMethods } from „@ngrx/signals“;

export function withCrudOperations() {
 return signalStoreFeature(
   withMethods((store) => ({
     load: (crudService: CrudOperations) => crudService.load(),
     update: (crudableObject: CRUD, crudService: CrudOperations) => {
       crudService.update(crudableObject);
       patchState(store, setEntity(crudableObject));
     },
   }),
 ));
}

export interface CrudOperations {
 load(): void;
 update(crudableObject: CRUD): void;
}

// Product & Customer services must extend the same interface.

export class ProductService implements CrudOperations {
 load(): void {
   console.log('load products');
 }
 update(): void {
   console.log('update products');
 }
}

export class CustomerService implements CrudOperations {
 load(): void {
   console.log('load customers');
 }
 update(): void {
   console.log('update customers');
 }
}

// and now let’s add this feature in our stores

export const ProductStore = signalStore(
 withCrudOperations(),
);


export const CustomerStore = signalStore(
 withCrudOperations(),
);

NGRX Toolkit-Dienstprogrammpaket

Da die Erweiterung so einfach ist, gibt es bereits ein Hilfspaket namens ngrx-toolkit, das den Signal Stores nützliche Tools hinzufügen soll.

SignalStore injizieren

{ bereitgestelltIn: ‚root‘ } oder im Provider-Array einer Komponente, eines Dienstes, einer Richtlinie usw.

DeepSignals

  • Verschachtelte Zustandseigenschaften werden als Signale gelesen und bei Bedarf träge generiert

patchState

  • Alternative API zum Festlegen und Aktualisieren (der Signal-API) zum Aktualisieren des Store-Status, es müssen nur die Werte angegeben werden, die wir ändern möchten

rxMethode

  • Dienstprogrammmethode, die die Verwendung von RxJS zusammen mit SignalStore oder signalState unterstützt

Leichtere Alternative mit SignalState

  • SignalState bietet eine Alternative zur Verwaltung des signalbasierten Zustands auf prägnante und minimalistische Weise.

Abschließende Gedanken

Es bleibt abzuwarten, wie zuverlässig es für größere Anwendungen ist, insbesondere wenn es als globaler Speicher eingesetzt wird.

Im Moment denke ich, dass es eine großartige Ergänzung zur Standard-Signal-API ist, was es zu einer guten Option für die Verwaltung macht:

  • Zustand auf Komponentenebene
  • Feature-basierter Status

Zusätzliche Ressourcen:

https://www.stefanos-lignos.dev/posts/ngrx-signals-store
https://www.angulararchitects.io/blog/the-new-ngrx-signal-store-for-angular-2-1-flavors/ (Gruppe von 4 Artikeln zum Thema)
https://ngrx.io/guide/signals

Das obige ist der detaillierte Inhalt vonDer Signal Store von NGRX – Aufschlüsselung der Hauptkonzepte. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn