Der Schöpfer von NGRX Signal Store, Marko Stanimirovic beschreibt hier NgRx SignalStore: Detaillierter Blick auf signalbasiertes Zustandsmanagement in Angular
Lassen Sie uns die API des Shops anhand von Codebeispielen erkunden. Wir verwenden ein Projekt mit einer Liste von Produkt- und Filterfunktionen.
import { signalStore } from "@ngrx/signals"; export const ProductStore = signalStore( … );
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); );
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; }) })),
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 über den Store zugegriffen werden kann. Sie laufen auch in einem Injektionskontext, der es ermöglicht, Abhängigkeiten in sie einzuschleusen.
import { withHooks } from "@ngrx/signals"; export const ProductStore = signalStore( withHooks((store) => ({ onInit() { // Load products when the store is initialized store.loadProducts(); }, })), );
export const ProductStoreWithEntities = signalStore( withEntities(), // 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.
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, den Code 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, ) => { return products.filter(p => p.price >= lowPrice && p.price <= highPrice); }, getProductsByCategory: (category: string, products: Array ) => { 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(), );
Da die Erweiterung so einfach ist, gibt es bereits ein Hilfspaket namens ngrx-toolkit, das den Signal Stores nützliche Tools hinzufügen soll.
{ bereitgestelltIn: ‚root‘ } oder im Provider-Array einer Komponente, eines Dienstes, einer Richtlinie usw.
对于大型应用程序来说,它的可靠性还有待证明,尤其是作为全球商店应用时。
目前我认为这是对默认 Signal API 的一个很好的补充,使其成为管理的一个不错的选择:
https://www.stefanos-lignos.dev/posts/ngrx-signals-store
https://www.angulararchitects.io/blog/the-new-ngrx-signal-store-for-angular-2-1-flavors/(关于该主题的 4 篇文章)
https://ngrx.io/guide/signals
以上是Der Signal Store von NGRX – Aufschlüsselung der Hauptkonzepte的详细内容。更多信息请关注PHP中文网其他相关文章!