NGRX Signal Store 的創建者,Marko Stanimirovic 在此描述了 NgRx SignalStore:深入了解 Angular 中基於訊號的狀態管理
讓我們透過程式碼範例來探索商店的 API。我們將使用一個包含產品清單和過濾功能的項目。
import { signalStore } from "@ngrx/signals"; export const ProductStore = signalStore( … );
與迄今為止的任何 NGRX Store 一樣,可以使用函數 withState 來提供初始狀態,該函數接受物件文字、記錄或工廠函數(用於建立動態初始狀態)作為輸入。
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 & withCompulated 取得工廠函數並傳回可以透過使用存取的方法和計算訊號的字典商店。它們還在註入上下文中運行,這使得可以將依賴項注入到它們中。
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<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)); }, })),
可以新增以「with」開頭的多個功能,但它們只能存取先前定義的內容。
signalStoreFeature - 用於擴展商店的功能。
對於大型企業應用程式來說,商店可能會變得複雜且難以管理。在為專案編寫功能和元件時,拆分得越好、越細,就越容易管理、維護程式碼和為其編寫測試。
但是,考慮到 SignalStore 提供的 API,除非相應地拆分程式碼,否則儲存可能會變得難以管理。 signalStoreFeature 適合將功能(或組件)的特定功能提取到獨立的可測試函數中,該函數可能(並且理想情況下)可以在其他商店中重複使用。
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); }, })), ); }
現在是 signalStoreFeature 的範例,它展示了跨多個商店重複使用 signalStoreFeature 的可能性。
從「@ngrx/signals」導入{ patchState, signalStoreFeature, withMethods };
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 的實用程式包,旨在為訊號儲存添加有用的工具。
{providedIn: ‘root’} 或在元件、服務、指令等的提供者陣列中
對於大型應用程式來說,它的可靠性還有待證明,尤其是作為全球商店應用程式時。
目前我認為它是對預設 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
以上是NGRX 的訊號儲存 - 主要概念細分的詳細內容。更多資訊請關注PHP中文網其他相關文章!