Angular技术点(NgRxStore)

2019-12-18  本文已影响0人  桃子是水果

NgRx/Store

@ngrx/store是基于RxJS的状态管理库。在NgRx中,状态是由一个包含action和reducer的函数的映射组成的。Reducer函数经由action的分发以及当前或初始的状态而被调用,最后由reducer返回一个不可变的状态。

Action: Action是状态的改变。它描述了某个事件的发生,但是没有指定应用的状态如何改变。
ActionReducerMapActionReducerMap注册了一系列的reducer,在应用中使用StoreModule对它进行配置。
ActionReducer: 它被用于创建reducer,例如logger。
MetaReducer: 在应用中使用StoreModule配置的MetaReducer构成了根的meta-reducer。
StoreModule: StoreModule@ngrx/storeAPI中的一个模块,它被用来在应用模块中配置reducer。
createFeatureSelector: 它为状态(state)创建一个feature selector。
createSelector: 它创建一个selector用于生成一个指定的状态。
Store: 它提供了Store.select()Store.dispatch()来与reducer协同工作。Store.select()用于选择一个selector,Store.dispatch()用于向reducer分发action的类型。

一般使用ActionStore、以及一个自定义的State即可。


安装

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


创建项目中需要管理的状态(xx.state.ts)

State是一个单独的不可变的数据结构(可以理解为一个全局的共享数据集)。

export interface XXState {
  isXX: boolean;  // 某某状态
  yyArr: Array<any>  // 某个数据数组
}

State通过Store.dispatch()一个action进行变更。


创建项目中需要的Action类(xx.action.ts)

NgRx的Action描述了状态的变化。对于每一个action,我们都需要创建一个继承自Action的类,同时定义其type和payload(payload是个可选参数)。

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) {}
}

// 导出对应的actions
export type XXActions = ChangeXXAction |
                        ChangeYYAction;

创建项目中需要的Reducer类(xx.reducer.ts)

Reducer描述了任何一个action所对应的应用的state将怎样变化。

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

// 默认的初始数据,在状态改变过程中新状态将会覆盖默认数据
const initialState: XXState = {
  isXX: false,
  yyArr: ['DATA1','DATA2']
};

export function reducer(state = initialState, action:XXActions): XXState {
  switch(action.type) {
    case xAction.XX: {
      // ES2018的展开运算符合并对象,新的同key数据将会替换旧的
      // 否则就会添加新的key-value
      return {...initialState,isXX: true,yyArr: ['DATA3']};
    }
    case xAction.YY: {
      return {...initialState,isXX:payload.isXX,yyArr:payload.yyArr};
    }  
    default: {
      return state;
    }
  } 
} 

使用createSelector()创建选择器,用于绑定store数据

首先需要创建一个索引文件(index.ts(名称任意))用来管理所有的State:

export interface AppState {
  xx: XXState
  // 如果要管理多个状态,在这个接口中添加即可
}

// 引入需要的reducer
import * as xxReducer from './xx.reducer';
// 创建Action和Reducer间的映射关系(那个action走哪个reducer)
export const reducers: ActionReducerMap<AppState> = {
  xx: xxReducer.reducer,
};

// @ngrx/store默认使用 combineReducers创建根meta-reducer。
// 这里调用combineReducers即可
const developmentReducer = combineReducers(reducers);
// 如果在app.module.ts中不显示声明metaReducer的配置项目,那么这里可以省略
export function metaReducer( state: any, action: any) {
  return developmentReducer(state, action);
}


// 创建选择器对应选择的状态类型
export const getStateType = (state: AppState) => state.xx;
// 创建要监视的状态(猜测)
export const getXX = (state: XXState) => state.isXX;
// 创建选择器(一个选择器只能监视一个State接口中的属性)
export const getXXState = createSelector(
  getStateType,
  getXX
);

在app.module.ts中配置store:

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

在需要订阅数据的地方订阅数据(订阅后会自动更新):

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才能获取数据
  // 或者在前台使用"this.isXX$ | async"方式访问Observable对象
  // 前台直接访问的Observable对象变量一般后缀$ 
 subScriptions.push(this.store.select(stateRoot.getXXState).subscribe(value => this.isXX = value));
}

最终在销毁组件的时候取消订阅:

ngOnDestroy() {
    this.subScriptions.forEach(subScription => {
      subScription.unsubscribe();
    });
  }
上一篇下一篇

猜你喜欢

热点阅读