NgRx/Store
@ngrx/store
是基于RxJS的状态管理库。在NgRx中,状态是由一个包含action和reducer的函数的映射组成的。Reducer函数经由action的分发以及当前或初始的状态而被调用,最后由reducer返回一个不可变的状态。
Action: Action
是状态的改变。它描述了某个事件的发生,但是没有指定应用的状态如何改变。
ActionReducerMap: ActionReducerMap
注册了一系列的reducer,在应用中使用StoreModule
对它进行配置。
ActionReducer: 它被用于创建reducer,例如logger。
MetaReducer: 在应用中使用StoreModule
配置的MetaReducer
构成了根的meta-reducer。
StoreModule: StoreModule
是@ngrx/store
API中的一个模块,它被用来在应用模块中配置reducer。
createFeatureSelector: 它为状态(state)创建一个feature selector。
createSelector: 它创建一个selector用于生成一个指定的状态。
Store: 它提供了Store.select()
和Store.dispatch()
来与reducer协同工作。Store.select()
用于选择一个selector,Store.dispatch()
用于向reducer分发action的类型。
一般使用Action、Store、以及一个自定义的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();
});
}
网友评论