NgRx Store里的StoreModule.forRoot()

NgRx Store is mainly for managing global state across an entire application. In cases where you need to manage temporary or local component state, consider using NgRx ComponentStore.


NgRx Store是为了管理整个应用的全局状态而设计的,如果想管理局部Component状态或者临时状态,请使用NgRx ComponentStore.


NgRx Store里的StoreModule.forRoot()

Actions are the inputs and outputs of many systems in NgRx.


Actions是NgRx系统的输入和输出。


NgRx里标准的Action interface:NgRx Store里的StoreModule.forRoot()

export interface Action {
    type: string;
}


NgRx reducer的immutability特性

Each action handles the state transition immutably. This means that the state transitions are not modifying the original state, but are returning a new state object using the spread operator. The spread syntax copies the properties from the current state into the object, creating a new reference.


状态迁移并不会修改原始状态,而是借助三个点 … 即spread操作符,返回新的state对象。Spread 操作符会从当前state变量里拷贝属性,生成新的对象引用。


const scoreboardReducer = createReducer(
  initialState,
  on(ScoreboardPageActions.homeScore, state => ({ ...state, home: state.home + 1 })),
  on(ScoreboardPageActions.awayScore, state => ({ ...state, away: state.away + 1 })),
  on(ScoreboardPageActions.resetScore, state => ({ home: 0, away: 0 })),
  on(ScoreboardPageActions.setScores, (state, { game }) => ({ home: game.home, away: game.away }))
);
export function reducer(state: State | undefined, action: Action) {
  return scoreboardReducer(state, action);
}


When an action is dispatched, all registered reducers receive the action. Whether they handle the action is determined by the on functions that associate one or more actions with a given state change.


The state of your application is defined as one large object.


Registering reducer functions to manage parts of your state only defines keys with associated values in the object. To register the global Store within your application, use the StoreModule.forRoot() method with a map of key/value pairs that define your state.


The StoreModule.forRoot() registers the global providers for your application, including the Store service you inject into your components and services to dispatch actions and select pieces of state.


StoreModule.forRoot 为应用注册全局的服务提供者,包括注入到Component里的Store服务,以及用于dispatch actions的service以及选择state片段的服务。


Registering states with StoreModule.forRoot() ensures that the states are defined upon application startup. In general, you register root states that always need to be available to all areas of your application immediately.


使用StoreModule.forRoot注册的states,在应用startup之后立即处于可用状态。如果一个state在应用启动后,需要迅速被应用各个部分使用,那么需要注册成root state.


feature state

Feature states behave in the same way root states do, but allow you to define them with specific feature areas in your application. Your state is one large object, and feature states register additional keys and values in that object.


下面的代码,给应用注册了一个空的root state:

import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';

@NgModule({
  imports: [
    StoreModule.forRoot({})
  ],
})
export class AppModule {}

feature module的注册方法:

import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import * as fromScoreboard from './reducers/scoreboard.reducer';

@NgModule({
  imports: [
    StoreModule.forFeature(fromScoreboard.scoreboardFeatureKey, fromScoreboard.reducer)
  ],
})
export class ScoreboardModule {}

只要在app.module.ts里将包含了上述feature state的module import,就能做到feature state的eager import:

import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import { ScoreboardModule } from './scoreboard/scoreboard.module';

@NgModule({
  imports: [
    StoreModule.forRoot({}),
    ScoreboardModule
  ],
})
export class AppModule {}

selector

Selectors are pure functions used for obtaining slices of store state.


纯函数,唯一作用就是获得store state的片段数据。


Selectors provide many features when selecting slices of state:


Portability

Memoization

Composition

Testability

Type Safety

When using the createSelector and createFeatureSelector functions @ngrx/store keeps track of the latest arguments in which your selector function was invoked.


使用createSelector和createFeatureSelector之后,ngRx框架代码会记录当我们的selector被调用时,传入的输入参数。这么做的动机是,selectors是纯函数,因此相同的输入一定会产生相同的输出,所以ngRx把每次输入以及输出都缓存起来,如果下次调用selector的输入在缓存里有记录,即从缓存里返回输出数据,以提高性能。


这种行为称为memoization.


下图的代码,调用createFeatureSelector传入一个字符串,创建一个feature selector:


NgRx Store里的StoreModule.forRoot()


返回类型为MemoizedSelector,即带有记忆功能的selector.


createSelector的输入参数,以及返回的类型仍然是selector:


NgRx Store里的StoreModule.forRoot()


createSelector支持传入多达8个selector,来实现更复杂的取数逻辑。看个例子:


The createSelector function can take up to 8 selector functions for more complete state selections.


For example, imagine you have a selectedUser object in the state. You also have an allBooks array of book objects.

And you want to show all books for the current user.

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


The createFeatureSelector is a convenience method for returning a top level feature state. It returns a typed selector function for a feature slice of state.


上一篇:一个字稳!云原生产品家族支撑冬奥会九大业务场景,打造云上奥运新体验


下一篇:【树形动态规划】【CTSC1997】选课 解题报告