(1) 定义action
从@ngrx/store导入Action,新建一个Action的子类:

(2) 实现reducer,根据不同的action type,返回不同的store
store要存储的业务数据也定义在reducer里,当然也可以在单独的State.ts文件里实现:
import {createFeatureSelector, createSelector} from '@ngrx/store';
首先创建一个MemoizedSelector, 使用API createFeatureSelector:
export const getExampleState = createFeatureSelector<State>('example');
传入的类型参数为实际的业务数据类型,传入一个字符串作为selector的名称。
如果想通过state拿到具体的业务数据,调用createSelector,传入之前的FeatureSelector,以及一个map函数,该函数输入是一个state,输出是state包含的具体业务数据字段。
// 参数1:所有页面数据的一个抽象
// 参数2:如何通过state拿到包裹的业务数据
// 这算是Counter State的一个抽象,可以近似理解成页面数据State的一个子集
// 注意,这里的state.counter还不是具体的number,而是fromCounter.State,即: counter: fromCounter.State; 而fromCounter.State的定义:
/*
export interface State {
counter: number;
}
*/
export const getCounterState = createSelector(getExampleState, (state: State) => state.counter);
还可以像搭积木一样,将createSelector返回的MemoizedSelector传给新的createSelector,像拼乐高一样构造出新的selector:
// 这个函数最后要传给store.select, 作为一个map function
/*
输入1:某个具体的State,比如CounterState
输入2:如何根据State拿到具体的值
// select<K>(mapFn: (state: T) => K): Observable<K>;
this.counter$ = store.select(fromExample.getCounterCounter);
*/
export const getCounterCounter = createSelector(getCounterState, fromCounter.getCounter);
(3) 应用程序的定义:
这个counter的赋值逻辑:
(1) 使用构造函数注入一个Store对象,类型参数为具体的业务数据结构
(2) 使用之前调用createSelector得到的selector,作为输入参数,传入到store对象的
select方法里。
最后在页面里直接用$counter | async就可以显示当前的counter值了。
当然对counter的修改不能直接使用selector,实际上selector提供的只有读取方法;而是用store的dispatch方法,传入新的action来间接实现store里的数据修改动作。
最后一个步骤,在app module里从@ngrx/store导入StoreModule:
然后使用StoreModule.forFeature方法返回一个ModuleWithProviders: