Angular技術(shù)點(NgRxStore)

NgRx/Store

@ngrx/store是基于RxJS的狀態(tài)管理庫。在NgRx中,狀態(tài)是由一個包含action和reducer的函數(shù)的映射組成的。Reducer函數(shù)經(jīng)由action的分發(fā)以及當前或初始的狀態(tài)而被調(diào)用,最后由reducer返回一個不可變的狀態(tài)。

Action: Action是狀態(tài)的改變。它描述了某個事件的發(fā)生,但是沒有指定應(yīng)用的狀態(tài)如何改變。
ActionReducerMapActionReducerMap注冊了一系列的reducer,在應(yīng)用中使用StoreModule對它進行配置。
ActionReducer: 它被用于創(chuàng)建reducer,例如logger。
MetaReducer: 在應(yīng)用中使用StoreModule配置的MetaReducer構(gòu)成了根的meta-reducer。
StoreModule: StoreModule@ngrx/storeAPI中的一個模塊,它被用來在應(yīng)用模塊中配置reducer。
createFeatureSelector: 它為狀態(tài)(state)創(chuàng)建一個feature selector。
createSelector: 它創(chuàng)建一個selector用于生成一個指定的狀態(tài)。
Store: 它提供了Store.select()Store.dispatch()來與reducer協(xié)同工作。Store.select()用于選擇一個selector,Store.dispatch()用于向reducer分發(fā)action的類型。

一般使用Action、Store、以及一個自定義的State即可。


安裝

npm安裝即可,npm i @ngrx/store --save


創(chuàng)建項目中需要管理的狀態(tài)(xx.state.ts)

State是一個單獨的不可變的數(shù)據(jù)結(jié)構(gòu)(可以理解為一個全局的共享數(shù)據(jù)集)。

export interface XXState {
  isXX: boolean;  // 某某狀態(tài)
  yyArr: Array<any>  // 某個數(shù)據(jù)數(shù)組
}

State通過Store.dispatch()一個action進行變更。


創(chuàng)建項目中需要的Action類(xx.action.ts)

NgRx的Action描述了狀態(tài)的變化。對于每一個action,我們都需要創(chuàng)建一個繼承自Action的類,同時定義其type和payload(payload是個可選參數(shù))。

export const XX = 'xx';
export const YY = 'yy';

// 每個action其實就定義了一個類型,action的類型
export class ChangeXXAction implements Action {
  readonly type = XX;
  constructor() {}
}
export class ChangeYYAction implements Action {
  readonly type = YY;
  constructor(public payload: any) {}
}

// 導(dǎo)出對應(yīng)的actions
export type XXActions = ChangeXXAction |
                        ChangeYYAction;

創(chuàng)建項目中需要的Reducer類(xx.reducer.ts)

Reducer描述了任何一個action所對應(yīng)的應(yīng)用的state將怎樣變化。

// 引入action中定義的變量
import * as xAction from './xx.action';

// 默認的初始數(shù)據(jù),在狀態(tài)改變過程中新狀態(tài)將會覆蓋默認數(shù)據(jù)
const initialState: XXState = {
  isXX: false,
  yyArr: ['DATA1','DATA2']
};

export function reducer(state = initialState, action:XXActions): XXState {
  switch(action.type) {
    case xAction.XX: {
      // ES2018的展開運算符合并對象,新的同key數(shù)據(jù)將會替換舊的
      // 否則就會添加新的key-value
      return {...initialState,isXX: true,yyArr: ['DATA3']};
    }
    case xAction.YY: {
      return {...initialState,isXX:payload.isXX,yyArr:payload.yyArr};
    }  
    default: {
      return state;
    }
  } 
} 

使用createSelector()創(chuàng)建選擇器,用于綁定store數(shù)據(jù)

首先需要創(chuàng)建一個索引文件(index.ts(名稱任意))用來管理所有的State:

export interface AppState {
  xx: XXState
  // 如果要管理多個狀態(tài),在這個接口中添加即可
}

// 引入需要的reducer
import * as xxReducer from './xx.reducer';
// 創(chuàng)建Action和Reducer間的映射關(guān)系(那個action走哪個reducer)
export const reducers: ActionReducerMap<AppState> = {
  xx: xxReducer.reducer,
};

// @ngrx/store默認使用 combineReducers創(chuàng)建根meta-reducer。
// 這里調(diào)用combineReducers即可
const developmentReducer = combineReducers(reducers);
// 如果在app.module.ts中不顯示聲明metaReducer的配置項目,那么這里可以省略
export function metaReducer( state: any, action: any) {
  return developmentReducer(state, action);
}


// 創(chuàng)建選擇器對應(yīng)選擇的狀態(tài)類型
export const getStateType = (state: AppState) => state.xx;
// 創(chuàng)建要監(jiān)視的狀態(tài)(猜測)
export const getXX = (state: XXState) => state.isXX;
// 創(chuàng)建選擇器(一個選擇器只能監(jiān)視一個State接口中的屬性)
export const getXXState = createSelector(
  getStateType,
  getXX
);

在app.module.ts中配置store:

 imports: [
   ...
   StoreModule.forRoot(reducers), // 上文中的reducers,需要引入
    ...
  ],

在需要訂閱數(shù)據(jù)的地方訂閱數(shù)據(jù)(訂閱后會自動更新):

import * as stateRoot from './states/index';
import { Subscription } from 'rxjs';

private subScriptions: Array<Subscription> = [];
... 
// 注入stroe
constructor(private store: Store<stateRoot.AppState>) ...
...
...

someFunc():void {
  // 訂閱 
  // 這里返回的是Observable對象,需要進一步subscribe才能獲取數(shù)據(jù)
  // 或者在前臺使用"this.isXX$ | async"方式訪問Observable對象
  // 前臺直接訪問的Observable對象變量一般后綴$ 
 subScriptions.push(this.store.select(stateRoot.getXXState).subscribe(value => this.isXX = value));
}

最終在銷毀組件的時候取消訂閱:

ngOnDestroy() {
    this.subScriptions.forEach(subScription => {
      subScription.unsubscribe();
    });
  }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容