Angular 狀態管理方案調研


1 / 狀態管理

Rxjs + Service 組件內管理狀態:在組件中可以聲明一個屬性,作為組件的內存存儲。每次操作時調用服務(service)中的方法,然后手動更新狀態。

export class TodoComponent { todos : Todo[] = []; // 在組件中建立一個內存TodoList數組 constructor( @Inject('todoService') private service, ) {} addTodo(){ this.service .addTodo('test') // 通過服務新增數據到服務器數據庫 .then(todo => { // 更新todos的狀態 this.todos.push(todo); // 使用了可改變的數組操作方式 }); } }

Rxjs + Service 組件只需訪問,狀態在服務中存儲管理:在服務中定義一個內存存儲,然后在更新服務數據后手動更新內存存儲,組件中只需要訪問該屬性即可。

export class TodoService { private _todos: BehaviorSubject; private dataStore: { // 我們自己實現的內存數據存儲 todos: Todo[] }; constructor() { this.dataStore = { todos: [] }; this._todos = new BehaviorSubject([]); } get todos(){ return this._todos.asObservable(); } addTodo(desc:string){ let todoToAdd = {}; this.http .post(...) .map(res => res.json() as Todo) //通過服務新增數據到服務器數據庫 .subscribe(todo => { this.dataStore.todos = [...this.dataStore.todos, todo]; //推送給訂閱者新的內存存儲數據 this._todos.next(Object.assign({}, this.dataStore).todos); }); } }

類 Redux 管理方案- ngrx & ngxs

其他未調研產品- Akita & mobX & Redux & Flux

 

2 / ngrx

ngrx/store的靈感來源於Redux,是一款集成RxJS的Angular狀態管理庫,由Angular的布道者Rob Wormald開發。它和Redux的核心思想相同,但使用RxJS實現觀察者模式。它遵循Redux核心原則,但專門為Angular而設計。

基本原則/概念

State(狀態) 是指單一不可變數據

Action(行為) 描述狀態的變化

Reducer(歸約器/歸約函數) 根據先前狀態以及當前行為來計算出新的狀態

狀態用State的可觀察對象,Action的觀察者——Store來訪問

 

 

Actions- Actions是信息的載體,它發送數據到reducer,然后reducer更新store。Actions是store能接受數據的唯一方式。在ngrx/store里,Action的 接口 是這樣的:

export interface Action { type: string; payload?: any; }

 

 

Reducers- Reducers規定了行為對應的具體狀態變化。它是純函數,通過接收前一個狀態和派發行為返回新對象作為下一個狀態的方式來改變狀態,新對象通常用Object.assign和擴展語法來實現。

export const todoReducer = (state = [], action) => { switch(action.type) { case 'ADD_TODO': return [...state, action.payload]; default: return state; } }

 

Store - store中儲存了應用中所有的不可變狀態。ngrx/store中的store是RxJS狀態的 可觀察對象 ,以及行為的 觀察者 。我們可以利用Store來派發行為。當然,我們也可以用Store的select()方法獲取可觀察對象,然后訂閱觀察,在狀態變化之后做出反應。

Selector - 可見示例代碼

 

Effects- Redux 中的 Reducer 已經是一個純函數,而且是完全的只對狀態數據進行處理的純函數。在發出某個 Action 之后,Reducer 會對狀態數據進行處理然后返回。但一般來說,其實在執行 Action 后我們還是經常會可以稱為 Effect 的動作,比如:進行 HTTP 請求,導航,寫文件等等。而這些事情恰恰是 Redux 本身無法解決的,@ngrx/effects 用於解決這類場景,一個 http 請求的示例如下 https://gist.github.com/hijiangtao/d4def77867ff4aec2740ba6ab83b24bf

@Component({
   template: ` <div *ngFor="let movie of movies$ | async"> </div> ` }) export class MoviesPageComponent { movies$: Observable<Movie[]> = this.store.select(state => state.movies); constructor(private store: Store<{ movies: Movie[] }>) {} ngOnInit() { this.store.dispatch({ type: '[Movies Page] Load Movies' }); } }

 

 

最佳實踐

 

根 store 模塊 - 創建根 store 模塊作為一個完整的 Angular 模塊,與 NgRx 的 store 邏輯綁定在一起。功能 store 模塊將被導入到根 store 中,這樣唯一的根 store 模塊將被導入到應用程序的主 App Module 模塊中。

創建功能 store 模塊

 

方式一:Entity Feature Module - 定義 actions / 創建 state / 創建 reducer / 創建 selector / 創建 effects

方式二:標准的功能模塊 - 同上

模塊導入 angular - app.module.ts 引入

 

 

 

優勢

豌豆資源搜索網站https://55wd.com 廣州vi設計公司http://www.maiqicn.com

中心化,狀態不可變 - 所有相關應用程序的狀態都緩存在一個位置。這樣可以很容易地跟蹤問題,因為錯誤時的狀態快照可以提供重要的見解,並且可以輕松的重新重現這個問題。這也使得眾多困難問題,例如在Store應用程序的上下文中撤消/重做某一步驟,並且實現了更強大的功能的工具。

性能 - 由於狀態集合中應用程序的頂層,因為數據更新可以通過組件依賴於Store。Angular構建如這樣的數據流布置進行優化,並且可以在組件依賴於沒有發布新值的Observables的情況下禁用變化檢測。

測試 - 所有狀態更新都是在recudes中處理的,它們是純函數。純函數測試非常簡單,因為它只是輸入,反對輸出。這樣可以測試應用程序中最關鍵的方面,而無需使用mock,或其他的測試技巧,可以使測試復雜且容易出錯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM