Cet article vous donnera une compréhension approfondie du gestionnaire d'état de angular, NgRx, et vous présentera comment utiliser NgRx. J'espère qu'il sera utile à tout le monde !
NgRx est une solution d'architecture Redux pour la gestion globale de l'état dans les applications angulaires. [Recommandations de tutoriel associées : "tutoriel angulaire"]
@ngrx/store : Module de gestion de l'état global
@ngrx/effects : Gestion des effets secondaires
@ngrx/store-devtools : Les outils de débogage du navigateur doivent s'appuyer sur Redux Devtools Extension
@ngrx/schematics : outil de ligne de commande pour générer rapidement des fichiers NgRx
@ngrx/entity : améliorer l'efficacité des développeurs exploitant les données dans Réducteur
@ngrx/router-store : Synchronisez l'état de routage avec le Store global
1 Téléchargez NgRx
npm install @ngrx/store @ngrx/effects @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. Configurez 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. Créer un magasinng store State --root --module app.module.ts --statePath store --stateInterface AppState
4 Créer une 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> {}
ng g réducteur store/reducers/counter --skipTests --reducers=../index.ts < /code><p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">export const adapter: EntityAdapter<Todo> = createEntityAdapter<Todo>()
// 获取初始状态 可以传递对象参数 也可以不传
// {ids: [], entities: {}}
export const initialState: State = adapter.getInitialState()</pre><div class="contentsignin">Copier après la connexion</div></div></p><p>6. Créer un sélecteur</p><p></p><code>ng g selector store/selectors/counter --skipTests
// selectTotal 获取数据条数 // selectAll 获取所有数据 以数组形式呈现 // selectEntities 获取实体集合 以字典形式呈现 // selectIds 获取id集合, 以数组形式呈现 const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors();
export const selectTodo = createFeatureSelector<AppState, State>(todoFeatureKey) export const selectTodos = createSelector(selectTodo, selectAll)
Action Payload
1. Transmettez les paramètres lors de l'utilisation de la répartition dans le composant pour déclencher l'action, et les paramètres seront finalement placés dans l'objet Action. import { StoreRouterConnectingModule } from "@ngrx/router-store"
@NgModule({
imports: [
StoreRouterConnectingModule.forRoot()
]
})
export class AppModule {}
import * 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)
// 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) } }
metaReducer est un hook entre Action -> Réducteur, permettant aux développeurs de prétraiter l'action (appelée avant l'appel de la fonction normale du réducteur). rrreeeEffet
Exigence : Ajoutez un bouton à la page, et après avoir cliqué sur le bouton, attendez une seconde pour augmenter la valeur. 1. Ajoutez un bouton pour l'incrémentation de valeur asynchrone dans le modèle de composant. Une fois le bouton cliqué, exécutez la méthodeincrement_async
rrreee2. Ajoutez increment_async dans le code de la classe du composant. > méthode, et déclenchez l'action qui effectue l'opération asynchrone dans la méthode<span style="font-size: 18px;">rrreee</span>3. Ajoutez l'action qui effectue l'opération asynchrone dans le fichier d'action
rrreee
ng g effect store/effects/counter --root --module app.module.ts --skipTests
La fonction d'effet est fournie par le module @ngrx/effects, donc les modules associés doivent être importés dans le module racine Dépend de 🎜rrreee🎜🎜Entity🎜🎜🎜🎜🎜1 Présentation🎜🎜🎜🎜L'entité est traduite par entité et l'entité est une donnée de la collection. 🎜🎜NgRx fournit des objets adaptateur d'entité. Sous les objets adaptateur d'entité, diverses méthodes pour exploiter les entités de la collection sont fournies. Le but est d'améliorer l'efficacité des développeurs exploitant les entités. 🎜🎜🎜🎜2. Core🎜🎜🎜🎜1. EntityState : interface de type d'entité🎜rrreee🎜2. createEntityAdapter : créer un objet adaptateur d'entité🎜🎜3. Méthode d'instance🎜 🎜🎜🎜https://ngrx.io/guide/entity/adapter#adapter-collection-methods🎜🎜🎜🎜4 Sélecteur🎜🎜🎜rrreeerrreee🎜🎜Router Store🎜🎜🎜🎜🎜1. 🎜 🎜1) Présentez le module 🎜rrreee🎜2) Intégrez le statut de routage dans Store🎜rrreee🎜🎜🎜2 Créez un sélecteur pour obtenir le statut de routage🎜🎜🎜rrreeerrreee🎜Pour plus de connaissances sur la programmation, veuillez visiter : 🎜Vidéo de programmation🎜 ! ! 🎜Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!