select:this.store.pipe(select('countInfo')) // 获取这个状态的值
dispatch:this.store.dispatch(increment()); // 触发对应的事件来更改countInfo的值
app/ngrx目录
header.action.ts
import { createAction,props } from '@ngrx/store';
export const increment = createAction('[Counter Component] Increment');
export const decrement = createAction('[Counter Component] Decrement');
export const reset = createAction(
'[Counter Component] Reset',
props<{count:number}>()
);
header.reducer.ts
import { createReducer, on } from '@ngrx/store';
import { increment, decrement, reset } from '../actions/header.action';
export interface State {
count:number
};
export const initialState: State = {count:0};
const _counterReducer = createReducer(initialState,
on(increment, state => ({...state,count:state.count-1})), // 计数器+1
on(decrement, state => ({...state,count:state.count+1})), // 计数器-1
on(reset, (state,action) => ({...state,count:action.count})), // 计数器重置
);
export function counterReducer(state, action) {
return _counterReducer(state, action);
}
app/ngrx/reducers/index.ts
import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import * as counterReducer from 'src/app/ngrx/reducers/header.reducer';
// import * as loginReducer from 'src/app/ngrx/reducers/login.reducer';
export interface State {
countInfo:counterReducer.State,
//userInfo:loginReducer.State
}
const initialState: State = {
countInfo: counterReducer.initialState,
//userInfo: loginReducer.initialState
};
const reducers = {
countInfo: counterReducer.counterReducer,
// userInfo:loginReducer.loginReducer
}
@NgModule({
imports: [
StoreModule.forRoot(reducers),
// StoreModule.forFeature('countInfo',counterReducer.counterReducer),
// StoreModule.forFeature('userInfo',loginReducer.loginReducer),
]
})
export class AppStoreModule {}
最后记得在app.module.ts中 imports:[AppStoreModule]
在具体的组件中使用使用,然后就可以看到页面有几个按钮,点击不同的按钮就可以实现count 的增减和重置:
/* .ts文件 */
import * as fromReducer from 'src/app/ngrx/reducers/index';
constructor(private store:Store) {
this.countInfo$ = store.pipe(select('countInfo'));
//this.userInfo$.subscribe(item=>console.log(item))
}
increment() {this.store.dispatch(increment());}
decrement() {this.store.dispatch(decrement()); }
this.store.dispatch(reset({count:10}));
/*.html文件*/
{{ (countInfo$ | async).count }}
上面的代码:
forRoot():注册根状态:
应用程序的状态被定义为一个大对象。注册化简函数以管理部分状态时,只会在对象中定义具有关联值的键。要Store
在应用程序中注册全局StoreModule.forRoot()
变量,请将该方法与定义状态的键/值对映射一起使用。这些StoreModule.forRoot()
注册器为您的应用程序注册了全局提供程序,包括Store
您注入到组件和服务中的服务,以分派操作并选择状态
forFeature() :注册功能状态:
功能状态的行为与根状态相同,但是允许您在应用程序中使用特定功能区域定义它们。您的状态是一个大对象,功能状态在该对象中注册了其他键和值。
如果要使用StoreModule.forFeature,需要再app.module.ts里面imports:[StoreModule.forRoot({})]
参考:https://ngrx.io/guide/store/selectors
createSelector会跟踪调用选择器函数的最新参数。因为选择器是纯函数,所以当参数匹配时可以返回最后的结果,而无需重新调用选择器函数。这可以提供性能优势,尤其是对于执行昂贵计算的选择器而言。这种做法称为记忆
对一个状态使用选择器
app/ngrx/reducers/index.ts增加如下代码
import { createSelector } from '@ngrx/store';
import * as counterReducer from 'src/app/ngrx/reducers/header.reducer';
export interface State {
countInfo:counterReducer.State,
}
// 在State状态中筛选出countInfo
export const selectCountInfo = (state: State) => state.countInfo;
// 筛选出count 调用 store.pipe(select((()=>fromReducer.selectFeatureCount)()))
export const selectFeatureCount = createSelector(
selectCountInfo,
(state: counterReducer.State) => state.count
);
在组件中使用,结果,实时输出count的结果
import * as fromReducer from 'src/app/ngrx/reducers/index';
constructor(private store:Store) {
...
this.selectFeatureCount$ = store.pipe(select((()=>fromReducer.selectFeatureCount)()));
this.selectFeatureCount$.subscribe(item=>console.log(item));
}
对多个状态使用选择器
的createSelector
可用于选择从状态的一些数据基于相同状态的几个切片。该createSelector
功能最多可使用8个选择器功能,以进行更完整的状态选择。例如,假设您有一个selectedUser
处于状态的对象。您还具有allBooks
一系列的书本对象。您想显示当前用户的所有图书。您可以createSelector
用来实现这一目标。即使您在中更新了可见的图书,它们也会始终保持最新状态allBooks
。如果选择一本,它们将始终显示属于您用户的图书,而当未选择任何用户时,它们将显示所有图书。结果将只是状态的另一部分过滤掉您的某些状态。而且它将永远是最新的。
import { createSelector } from '@ngrx/store';
export interface User {
id: number;
name: string;
}
export interface Book {
id: number;
userId: number;
name: string;
}
export interface AppState {
selectedUser: User;
allBooks: Book[];
}
export const selectUser = (state: AppState) => state.selectedUser;
export const selectAllBooks = (state: AppState) => state.allBooks;
export const selectVisibleBooks = ()=> createSelector(
selectUser,
selectAllBooks,
(selectedUser: User, allBooks: Book[]) => {
if (selectedUser && allBooks) {
return allBooks.filter((book: Book) => book.userId === selectedUser.id);
} else {
return allBooks;
}
}
);
/*
上面代码中,是对两个状态操作,在allBooks数组中筛选userId等于selectedUser.id:
(selectedUser: User, allBooks: Book[]) => {...}
selectedUser为(state: AppState) => state.selectedUser的返回结果
allBooks为(state: AppState) => state.allBooks的返回结果
*/
// 在组件中使用:
import * as fromReducer from 'src/app/ngrx/reducers/index';
constructor(private store:Store) {
...
this.selectBooks$ = store.pipe(select(fromReducer.selectVisibleBooks()));
this.selectBooks$.subscribe(item=>console.log(item));
}
使用selecotr props
app/ngrx/reducers/index.ts新增如下代码
export interface State {
countInfo:counterReducer.State,
}
export const getCount = () =>
createSelector(
(state, props) => state.countInfo[props.id],
(counter, props) => counter * props.multiply
);
// props.id 和props.multiply 都是传进来的;
// (counter, props)=>... 中的counter为上一个(state, props) => state.countInfo[props.id]的结果
// 如:当state.countInfo[props.id]等于2的时候,counter等于2
在组件中使用:
constructor(private store:Store) {
this.counter$ = store.pipe(select(fromReducer.getCount(), { id: 'count', multiply: 2 }));
this.counter$.subscribe(item=>console.log(item));
}
// this.counter$结果:
// 当count为0的时候(counter$ | async ) 0
// 当count为2的时候(counter$ | async ) 4
createFeatureSelector
这createFeatureSelector
是用于返回顶级要素状态的便捷方法。它为状态要素切片返回类型选择器函数。
// 直接返回State的类型为counterReducer.State的countInfo
export const selectFeature = createFeatureSelector('countInfo');
export const selectFeatureCounts = ()=> createSelector(
selectFeature,
(state: counterReducer.State) => state.count
);
// (state: counterReducer.State) => state.count中state为selectFeature的返回结果
源码