ngrx 的简单使用

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<fromReducer.State>) { 
      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文件*/
<div>{{ (countInfo$ | async).count }}</div>
<button id="increment" (click)="increment()">Increment</button>
<button id="decrement" (click)="decrement()">Decrement</button>
<button id="reset" (click)="reset()">Reset Counter</button>

上面的代码:
forRoot():注册根状态:
应用程序的状态被定义为一个大对象。注册化简函数以管理部分状态时,只会在对象中定义具有关联值的键。要Store在应用程序中注册全局StoreModule.forRoot()变量,请将该方法与定义状态的键/值对映射一起使用。这些StoreModule.forRoot()注册器为您的应用程序注册了全局提供程序,包括Store您注入到组件和服务中的服务,以分派操作并选择状态
forFeature() :注册功能状态:
功能状态的行为与根状态相同,但是允许您在应用程序中使用特定功能区域定义它们。您的状态是一个大对象,功能状态在该对象中注册了其他键和值。
如果要使用StoreModule.forFeature,需要再app.module.ts里面imports:[StoreModule.forRoot({})] 

createSelector:选择器 

参考: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
export const selectFeatureCount = createSelector(
    selectCountInfo,
  (state: counterReducer.State) => state.count
);

在组件中使用,结果,实时输出count的结果

import * as fromReducer from 'src/app/ngrx/reducers/index';
constructor(private store:Store<fromReducer.State>) { 
      ...
      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<fromReducer.State>) { 
      ...
      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<fromReducer.State>) { 
      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<State, counterReducer.State>('countInfo');
 
export const selectFeatureCounts = ()=> createSelector(
  selectFeature,
  (state: counterReducer.State) => state.count
);

// (state: counterReducer.State) => state.count中state为selectFeature的返回结果
发布了112 篇原创文章 · 获赞 149 · 访问量 55万+

猜你喜欢

转载自blog.csdn.net/l284969634/article/details/102700896