Home >Web Front-end >JS Tutorial >Detailed explanation of angular learning state manager NgRx
This article will give you an in-depth understanding of angular's state manager NgRx, and introduce how to use NgRx. I hope it will be helpful to everyone!
NgRx is a Redux architecture solution for global state management in Angular applications. [Related tutorial recommendations: "angular tutorial"]
1. Download NgRx
npm install @ngrx/store @ngrx/effects @ngrx/entity @ngrx/router-store @ngrx/store-devtools @ngrx/schematics
2. Configure NgRx CLI
ng config cli.defaultCollection @ngrx/schematics
// angular.json "cli": { "defaultCollection": "@ngrx/schematics" }
3. Create Store
ng g store State --root --module app.module.ts --statePath store --stateInterface AppState
4 , create Action
ng g action store/actions/counter --skipTests
import { createAction } from "@ngrx/store" export const increment = createAction("increment") export const decrement = createAction("decrement")
5, create Reducer
ng g reducer store/reducers/counter --skipTests --reducers=../index.ts
import { createReducer, on } from "@ngrx/store" import { decrement, increment } from "../actions/counter.actions" export const counterFeatureKey = "counter" export interface State { count: number } export const initialState: State = { count: 0 } export const reducer = createReducer( initialState, on(increment, state => ({ count: state.count + 1 })), on(decrement, state => ({ count: state.count - 1 })) )
6. Create Selector
ng g selector store/selectors/counter --skipTests
import { createFeatureSelector, createSelector } from "@ngrx/store" import { counterFeatureKey, State } from "../reducers/counter.reducer" import { AppState } from ".." export const selectCounter = createFeatureSelector<AppState, State>(counterFeatureKey) export const selectCount = createSelector(selectCounter, state => state.count)
7. Component class triggers Action and gets status
import { select, Store } from "@ngrx/store" import { Observable } from "rxjs" import { AppState } from "./store" import { decrement, increment } from "./store/actions/counter.actions" import { selectCount } from "./store/selectors/counter.selectors" export class AppComponent { count: Observable<number> constructor(private store: Store<AppState>) { this.count = this.store.pipe(select(selectCount)) } increment() { this.store.dispatch(increment()) } decrement() { this.store.dispatch(decrement()) } }
8. Component template display status
<button (click)="increment()">+</button> <span>{{ count | async }}</span> <button (click)="decrement()">-</button>
this.store.dispatch(increment({ count: 5 }))2. When creating the Action Creator function, obtain the parameters and specify the parameter type.
import { createAction, props } from "@ngrx/store" export const increment = createAction("increment", props<{ count: number }>())
export declare function props<P extends object>(): Props<P>;3. Get parameters through Action object in Reducer.
export const reducer = createReducer( initialState, on(increment, (state, action) => ({ count: state.count + action.count })) )
function debug(reducer: ActionReducer<any>): ActionReducer<any> { return function (state, action) { return reducer(state, action) } } export const metaReducers: MetaReducer<AppState>[] = !environment.production ? [debug] : []
increment_async method
<button (click)="increment_async()">async</button>2. Add a new button in the component class Add the
increment_async method, and trigger the Action
increment_async() { this.store.dispatch(increment_async()) }in the method to perform the asynchronous operation. 3. Add the Action
export const increment_async = createAction("increment_async")to the Action file. 4. Create Effect, receive Action and perform side effects, continue to trigger Action
ng g effect store/effects/counter --root --module app.module.ts --skipTests## The #Effect function is provided by the @ngrx/effects module, so the relevant module dependencies need to be imported in the root module
import { Injectable } from "@angular/core" import { Actions, createEffect, ofType } from "@ngrx/effects" import { increment, increment_async } from "../actions/counter.actions" import { mergeMap, map } from "rxjs/operators" import { timer } from "rxjs" // createEffect // 用于创建 Effect, Effect 用于执行副作用. // 调用方法时传递回调函数, 回调函数中返回 Observable 对象, 对象中要发出副作用执行完成后要触发的 Action 对象 // 回调函数的返回值在 createEffect 方法内部被继续返回, 最终返回值被存储在了 Effect 类的属性中 // NgRx 在实例化 Effect 类后, 会订阅 Effect 类属性, 当副作用执行完成后它会获取到要触发的 Action 对象并触发这个 Action // Actions // 当组件触发 Action 时, Effect 需要通过 Actions 服务接收 Action, 所以在 Effect 类中通过 constructor 构造函数参数的方式将 Actions 服务类的实例对象注入到 Effect 类中 // Actions 服务类的实例对象为 Observable 对象, 当有 Action 被触发时, Action 对象本身会作为数据流被发出 // ofType // 对目标 Action 对象进行过滤. // 参数为目标 Action 的 Action Creator 函数 // 如果未过滤出目标 Action 对象, 本次不会继续发送数据流 // 如果过滤出目标 Action 对象, 会将 Action 对象作为数据流继续发出 @Injectable() export class CounterEffects { constructor(private actions: Actions) { // this.loadCount.subscribe(console.log) } loadCount = createEffect(() => { return this.actions.pipe( ofType(increment_async), mergeMap(() => timer(1000).pipe(map(() => increment({ count: 10 })))) ) }) }Entity
1, OverviewEntity is translated as entity, and entity is a piece of data in the collection.
NgRx provides entity adapter objects. Under the entity adapter objects, various methods for operating entities in the collection are provided. The purpose is to improve the efficiency of developers operating entities.
2. Core1. EntityState: Entity type interface
/* { ids: [1, 2], entities: { 1: { id: 1, title: "Hello Angular" }, 2: { id: 2, title: "Hello NgRx" } } } */ export interface State extends EntityState<Todo> {}
2. createEntityAdapter: Create entity adapter object
3. EntityAdapter: Entity Adapter Object Type Interface
export const adapter: EntityAdapter<Todo> = createEntityAdapter<Todo>() // 获取初始状态 可以传递对象参数 也可以不传 // {ids: [], entities: {}} export const initialState: State = adapter.getInitialState()
3. Instance Methodhttps://ngrx.io /guide/entity/adapter#adapter-collection-methods
4. Selector// selectTotal 获取数据条数
// selectAll 获取所有数据 以数组形式呈现
// selectEntities 获取实体集合 以字典形式呈现
// selectIds 获取id集合, 以数组形式呈现
const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors();
rrree
1. Synchronize routing status1)Introduce module
export const selectTodo = createFeatureSelector<AppState, State>(todoFeatureKey) export const selectTodos = createSelector(selectTodo, selectAll)
2)Integrate routing status into Store
import { StoreRouterConnectingModule } from "@ngrx/router-store" @NgModule({ imports: [ StoreRouterConnectingModule.forRoot() ] }) export class AppModule {}
2. Create a Selector to obtain routing statusimport * as fromRouter from "@ngrx/router-store"
export interface AppState {
router: fromRouter.RouterReducerState
}
export const reducers: ActionReducerMap<AppState> = {
router: fromRouter.routerReducer
}
// router.selectors.ts
import { createFeatureSelector } from "@ngrx/store"
import { AppState } from ".."
import { RouterReducerState, getSelectors } from "@ngrx/router-store"
const selectRouter = createFeatureSelector<AppState, RouterReducerState>(
"router"
)
export const {
// 获取和当前路由相关的信息 (路由参数、路由配置等)
selectCurrentRoute,
// 获取地址栏中 # 号后面的内容
selectFragment,
// 获取路由查询参数
selectQueryParams,
// 获取具体的某一个查询参数 selectQueryParam('name')
selectQueryParam,
// 获取动态路由参数
selectRouteParams,
// 获取某一个具体的动态路由参数 selectRouteParam('name')
selectRouteParam,
// 获取路由自定义数据
selectRouteData,
// 获取路由的实际访问地址
selectUrl
} = getSelectors(selectRouter)
For more programming-related knowledge, please visit:
The above is the detailed content of Detailed explanation of angular learning state manager NgRx. For more information, please follow other related articles on the PHP Chinese website!