이 글은 angular의 상태 관리자 NgRx에 대한 심층적인 이해를 제공하고, NgRx 사용법을 소개하는 글이 모든 분들께 도움이 되기를 바랍니다!
NgRx는 Angular 애플리케이션의 전역 상태 관리를 위한 Redux 아키텍처 솔루션입니다. [관련 튜토리얼 권장사항: "angular tutorial"]
@ngrx/store: 전역 상태 관리 모듈
@ngrx/events: 부작용 처리
@ngrx/store-devtools : 브라우저 디버깅 도구는 Redux Devtools Extension
@ngrx/schematics에 의존해야 함: NgRx 파일을 빠르게 생성하는 명령줄 도구
@ngrx/entity: Reducer에서 데이터를 운영하는 개발자의 효율성 향상
@ngrx/router-store: 라우팅 상태를 전역 Store
1에 동기화합니다. NgRx
npm install @ngrx/store @ngrx/efficent @ngrx/entity @ ngrx/router-store @ngrx/store-devtools @ngrx/schematics
npm install @ngrx/store @ngrx/effects @ngrx/entity @ngrx/router-store @ngrx/store-devtools @ngrx/schematics
2、配置 NgRx CLI
ng config cli.defaultCollection @ngrx/schematics
// angular.json "cli": { "defaultCollection": "@ngrx/schematics" }
3、创建 Store
ng g store State --root --module app.module.ts --statePath store --stateInterface AppState
4、创建 Action
ng g action store/actions/counter --skipTests
import { createAction } from "@ngrx/store" export const increment = createAction("increment") export const decrement = createAction("decrement")
5、创建 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、创建 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、组件类触发 Action、获取状态
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、组件模板显示状态
<button (click)="increment()">+</button> <span>{{ count | async }}</span> <button (click)="decrement()">-</button>
1、在组件中使用 dispatch 触发 Action 时传递参数,参数最终会被放置在 Action 对象中。
this.store.dispatch(increment({ count: 5 }))
2、在创建 Action Creator 函数时,获取参数并指定参数类型。
import { createAction, props } from "@ngrx/store" export const increment = createAction("increment", props<{ count: number }>())
export declare function props<P extends object>(): Props<P>;
3、在 Reducer 中通过 Action 对象获取参数。
export const reducer = createReducer( initialState, on(increment, (state, action) => ({ count: state.count + action.count })) )
metaReducer 是 Action -> Reducer 之间的钩子,允许开发者对 Action 进行预处理 (在普通 Reducer 函数调用之前调用)。
function debug(reducer: ActionReducer<any>): ActionReducer<any> { return function (state, action) { return reducer(state, action) } } export const metaReducers: MetaReducer<AppState>[] = !environment.production ? [debug] : []
需求:在页面中新增一个按钮,点击按钮后延迟一秒让数值增加。
1、在组件模板中新增一个用于异步数值增加的按钮,按钮被点击后执行 increment_async
方法
<button (click)="increment_async()">async</button>
2、在组件类中新增 increment_async
方法,并在方法中触发执行异步操作的 Action
increment_async() { this.store.dispatch(increment_async()) }
3、在 Action 文件中新增执行异步操作的 Action
export const increment_async = createAction("increment_async")
4、创建 Effect,接收 Action 并执行副作用,继续触发 Action
ng g effect store/effects/counter --root --module app.module.ts --skipTests
2. NgRx CLI
ng config cli.defaultCollection @ngrx/schematics
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 })))) ) }) }
구성 3. Storeng store State --root --module app.module.ts --statePath store --stateInterface AppState
4. Create Action
ng g action store/actions/counter --skipTests
/* { ids: [1, 2], entities: { 1: { id: 1, title: "Hello Angular" }, 2: { id: 2, title: "Hello NgRx" } } } */ export interface State extends EntityState<Todo> {}5. 리듀서 생성
ng g 리듀서 store/reducers/counter --skipTests --reducers=../index.ts <p><pre class="brush:js;toolbar:false;">export const adapter: EntityAdapter<Todo> = createEntityAdapter<Todo>()
// 获取初始状态 可以传递对象参数 也可以不传
// {ids: [], entities: {}}
export const initialState: State = adapter.getInitialState()</pre></p>
<p>6. 선택기 만들기</p>
<p></p>
<code>ng g 선택기 store/selectors/counter --skipTests
// selectTotal 获取数据条数 // selectAll 获取所有数据 以数组形式呈现 // selectEntities 获取实体集合 以字典形式呈现 // selectIds 获取id集合, 以数组形式呈现 const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors();7. 구성 요소 클래스가 작업을 트리거하고 상태를 가져옵니다
export const selectTodo = createFeatureSelector<AppState, State>(todoFeatureKey) export const selectTodos = createSelector(selectTodo, selectAll)
8. 구성 요소 템플릿 표시 상태
import { StoreRouterConnectingModule } from "@ngrx/router-store" @NgModule({ imports: [ StoreRouterConnectingModule.forRoot() ] }) export class AppModule {}Action Payload1. Action을 트리거하기 위해 구성 요소에서 디스패치를 사용할 때 매개 변수를 전달하면 매개 변수가 결국 Action 개체에 배치됩니다.
import * as fromRouter from "@ngrx/router-store" export interface AppState { router: fromRouter.RouterReducerState } export const reducers: ActionReducerMap<AppState> = { router: fromRouter.routerReducer }2. Action Creator 기능을 생성할 때 매개변수를 가져오고 매개변수 유형을 지정합니다.
// 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)
// home.component.ts import { select, Store } from "@ngrx/store" import { AppState } from "src/app/store" import { selectQueryParams } from "src/app/store/selectors/router.selectors" export class AboutComponent { constructor(private store: Store<AppState>) { this.store.pipe(select(selectQueryParams)).subscribe(console.log) } }
rrreeeMetaReducer
metaReducer는 Action -> Reducer 사이의 연결 고리로 개발자가 Action(일반 Reducer 함수가 호출되기 전에 호출됨)을 전처리할 수 있습니다.rrreee
Effect
요구 사항: 페이지에 버튼을 추가하고 버튼을 클릭한 후 1초 동안 지연하여 값을 높입니다. 1. 컴포넌트 템플릿에 비동기 값 증가를 위한 버튼을 추가합니다. 버튼을 클릭한 후 increment_async
메서드를 실행합니다.rrreee
rrreee3. Action 파일rrreee
4에 비동기 작업을 수행하는 Action을 추가하고 Action을 받아 Side Effect를 실행합니다. 계속해서 Action🎜🎜ng g effect store/효과/counter --root --module app.module.ts --skipTests🎜🎜Effect 함수를 트리거하세요. 관련 모듈은 루트 모듈에서 가져와야 합니다. 🎜rrreee🎜🎜Entity🎜🎜🎜🎜🎜1에 따라 다릅니다. 개요🎜🎜🎜🎜Entity는 엔터티로 번역되며 엔터티는 컬렉션의 데이터 조각입니다. 🎜🎜NgRx는 엔터티 어댑터 개체를 제공하며, 그 목적은 개발자가 엔터티를 운영하는 효율성을 높이는 것입니다. 🎜🎜🎜🎜2 🎜🎜🎜https://ngrx.io/guide/entity/adapter#adapter-collection-methods🎜🎜🎜🎜4. Selector🎜🎜🎜rrreeerrreee🎜🎜Router Store🎜🎜🎜🎜🎜1. 🎜 🎜 🎜1) 모듈 소개 🎜rrreee🎜2) 라우팅 상태를 Store🎜rrreee🎜🎜🎜2에 통합하여 라우팅 상태를 얻기 위한 선택기를 만듭니다🎜🎜🎜rrreeerrreee🎜더 많은 프로그래밍 관련 지식을 보려면 🎜프로그래밍 비디오🎜를 방문하세요! ! 🎜위 내용은 각도 학습 상태 관리자 NgRx에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!