Cet article vous donnera une compréhension approfondie du gestionnaire d'état NgRx d'Angular et vous présentera comment utiliser NgRx. J'espère qu'il vous sera utile !
NgRx est une solution d'architecture Redux pour la gestion globale de l'état dans les applications angulaires. [Tutoriels associés recommandés : "tutoriel angulaire"]
@ngrx/store : module de gestion globale de l'état
@ngrx/effects : Gestion des effets secondaires
@ngrx/store-devtools : outil de débogage du navigateur, doit s'appuyer sur l'extension Redux Devtools
@ngrx/schematics : outil en ligne de commande pour générer rapidement des fichiers NgRx
@ngrx/entity : Améliorer l'efficacité des développeurs dans l'exploitation des données dans Réducteur
@ngrx/router-store : Synchroniser l'état du routage avec le magasin global
1. Téléchargez NgRx
npm install @ngrx/store @ngrx/effects @ngrx/entity @ngrx/router-store @ngrx/store-devtools @ngrx/schematics
2. Configurez la CLI NgRx
ng config cli.defaultCollection @ngrx/schematics
// angulaire.json "cli": { "defaultCollection": "@ngrx/schematics" }
3. Créer une boutique
ng g store State --root --module app.module.ts --statePath store --stateInterface AppState
4. Créer une action
ng g action store/actions/counter --skipTests
importer { createAction } depuis "@ngrx/store" export const incrément = createAction("incrément") export const décrément = createAction("décrément")
5. Créer un réducteur
ng g reducer store/reducers/counter --skipTests --reducers=../index.ts
importer { createReducer, on } depuis "@ngrx/store" importer { décrémenter, incrémenter } depuis "../actions/counter.actions" export const counterFeatureKey = "compteur" État de l'interface d'exportation { compte : nombre } exporter const initialState : État = { compte : 0 } exporter const réducteur = createReducer ( état initial, on(increment, state => ({ count: state.count + 1 })), on(décrémentation, état => ({ count: state.count - 1 })) )
6. Créer un sélecteur
ng g selector store/selectors/counter --skipTests
importer { createFeatureSelector, createSelector } depuis "@ngrx/store" importer { counterFeatureKey, State } depuis "../reducers/counter.reducer" importer {AppState} depuis ".." export const selectCounter = createFeatureSelector<AppState, State>(counterFeatureKey) export const selectCount = createSelector (selectCounter, state => state.count)
7. La classe de composants déclenche l'action et obtient le statut
importer { select, Store } depuis "@ngrx/store" importer {Observable} depuis "rxjs" importer {AppState} depuis "./store" importer { décrémenter, incrémenter } depuis "./store/actions/counter.actions" importer { selectCount } depuis "./store/selectors/counter.selectors" classe d'exportation AppComponent { nombre : Observable<numéro> constructeur (magasin privé : Store<AppState>) { this.count = this.store.pipe(select(selectCount)) } incrément() { this.store.dispatch(increment()) } décrémenter() { this.store.dispatch(décrément()) } }
8. État d'affichage du modèle de composant
<bouton (clic)="increment()">+</bouton> <span>{{ compte | asynchrone }}</span> <bouton (clic)="décrément()">-</bouton>
1. Utilisez la répartition dans le composant pour transmettre des paramètres lors du déclenchement de l'action, et les paramètres seront finalement placés dans l'objet Action.
this.store.dispatch(increment({ count: 5 }))
2. Lors de la création de la fonction Action Creator, obtenez les paramètres et spécifiez le type de paramètre.
importer { createAction, props } depuis "@ngrx/store" export const incrément = createAction("increment", props<{ count: number }>())
export déclare la fonction props<P extends object>() : Props<P>;
3. Obtenez les paramètres via l'objet Action dans Réducteur.
exporter const réducteur = createReducer ( état initial, on(increment, (state, action) => ({ count: state.count + action.count })) )
metaReducer est un hook entre Action -> Réducteur, permettant aux développeurs de prétraiter Action (appelée avant les appels de fonction Réducteur ordinaires).
function debug(réducteur : ActionReducer<any>): ActionReducer<any> { fonction de retour (état, action) { réducteur de retour (état, action) } } exporter const metaReducers : MetaReducer<AppState>[] = !environment.production ?[déboguer] : []
Condition préalable : ajoutez un bouton à la page. Après avoir cliqué sur le bouton, attendez une seconde pour que la valeur augmente.
1. Ajoutez un bouton pour l'incrémentation de valeur asynchrone dans le modèle de composant. Une fois le bouton cliqué, la méthode increment_async
est exécutée.
<button (click)="increment_async()">async</button>
2. Ajoutez la méthode increment_async
à la classe de composant et déclenchez l'action pour effectuer des opérations asynchrones dans la méthode.
incrément_async() { this.store.dispatch(increment_async()) }
3. Ajoutez une action pour effectuer des opérations asynchrones dans le fichier d'action.
export const incrément_async = createAction("increment_async")
4. Créez un effet, recevez une action, effectuez des effets secondaires et continuez à déclencher une action.
ng g effect store/effects/counter --root --module app.module.ts --skipTests
La fonction Effect est fournie par le module @ngrx/effects, les dépendances du module pertinentes doivent donc être importées dans le module racine.
importer {Injectable} depuis "@angular/core" importer { Actions, createEffect, ofType } depuis "@ngrx/effects" importer {incrément, incrément_async } depuis "../actions/counter.actions" importer { mergeMap, map } depuis "rxjs/operators" importer {timer} depuis "rxjs" // créerEffet // Utilisé pour créer un effet, Effect est utilisé pour effectuer des effets secondaires. // Passe la fonction de rappel lors de l'appel de la méthode et renvoie l'objet Observable dans la fonction de rappel. L'objet Action à déclencher après l'exécution des effets secondaires // La valeur de retour de la fonction de rappel continue d'être renvoyée dans createEffect. méthode, et la valeur de retour finale est stockée dans Dans les propriétés de la classe Effect // Après avoir instancié la classe Effect, NgRx s'abonnera aux propriétés de la classe Effect Lorsque les effets secondaires seront terminés, il obtiendra l'objet Action à déclencher. et déclenchez l'action. //Actes // Lorsqu'un composant déclenche une action, l'effet doit recevoir l'action via le service Actions, donc dans la classe Effect, l'objet instance de la classe de service Actions est injecté dans la classe Effect via le paramètre constructeur // L'instance. L'objet de la classe de service Actions est Observable. Lorsqu'une action est déclenchée, l'objet Action lui-même sera émis sous forme de flux de données // ofType. // Filtre l'objet Action cible. // Le paramètre est la fonction Action Creator de l'action cible // Si l'objet Action cible n'est pas filtré, le flux de données ne continuera pas à être envoyé cette fois // Si l'objet Action cible est filtré, l'objet Action continuera à être envoyé sous forme de flux de données @Injectable() classe d'exportation CounterEffects { constructeur (actions privées : actions) { // this.loadCount.subscribe(console.log) } loadCount = créerEffect(() => { renvoie this.actions.pipe( deType(increment_async), mergeMap(() => timer(1000).pipe(map(() => incrément({ count: 10 })))) ) }) }
1. Aperçu
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 entités exploitant les développeurs.
2. Noyau
1. EntityState : interface de type d'entité
/* { identifiants : [1, 2], entités : { 1 : { id : 1, titre : "Bonjour Angular" }, 2 : { id : 2, titre : "Bonjour NgRx" } } } */ L'état de l'interface d'exportation étend EntityState<Todo> {}
2. createEntityAdapter : créer un objet adaptateur d'entité
3. EntityAdapter : interface de type d'objet adaptateur d'entité
exporter l'adaptateur const : EntityAdapter<Todo> = createEntityAdapter<Todo>() // Récupère l'état initial Vous pouvez transmettre ou non les paramètres de l'objet. // {ids : [], entités : {}}. exporter const initialState : State = adapter.getInitialState()
3. Méthode des instances
https://ngrx.io/guide/entity/adapter#adapter-collection-methods
4. Sélecteur
// selectTotal récupère le nombre d'éléments de données // selectAll récupère toutes les données et les présente sous la forme d'un tableau // selectEntities récupère la collection d'entités et la présente sous la forme d'un dictionnaire // selectIds récupère la collection d'identifiants et la présente sous la forme d'un tableau const { selectIds, selectEntities, selectAll, selectTotal } = adapter .getSelectors();
export const selectTodo = createFeatureSelector<AppState, State>(todoFeatureKey) export const selectTodos = createSelector (selectTodo, selectAll)
1. Synchronisez l'état du routage
1) Présenter les modules
importer { StoreRouterConnectingModule } depuis "@ngrx/router-store" @NgModule({ importations : [ StoreRouterConnectingModule.forRoot() ] }) classe d'exportation AppModule {}
2) Intégrer le statut de routage dans Store
importer * en tant que fromRouter depuis "@ngrx/router-store" interface d'exportation AppState { routeur : fromRouter.RouterReducerState } exporter les réducteurs const : ActionReducerMap<AppState> = { routeur : fromRouter.routerReducer }
2. Créez un sélecteur pour obtenir le statut du routage
// routeur.selectors.ts importer { createFeatureSelector } depuis "@ngrx/store" importer {AppState} depuis ".." importer { RouterReducerState, getSelectors } depuis "@ngrx/router-store" const selectRouter = createFeatureSelector<AppState, RouterReducerState>( "routeur" ) exporter const { // Récupère les informations relatives à l'itinéraire actuel (paramètres de routage, configuration du routage, etc.) sélectionnezCurrentRoute, // Récupère le contenu après le numéro # dans la barre d'adresse selectFragment, // Récupère les paramètres de requête de routage selectQueryParams, // Récupère un paramètre de requête spécifique selectQueryParam('name') sélectionnezQueryParam, // Récupère les paramètres de routage dynamique selectRouteParams, // Récupère un paramètre de routage dynamique spécifique selectRouteParam('name') sélectionnezRouteParam, // Récupère les données personnalisées de l'itinéraire selectRouteData, // Récupère l'adresse d'accès réelle de la route selectUrl } = getSelectors (sélectionnerRouter)
// home.component.ts importer { select, Store } depuis "@ngrx/store" importer {AppState} depuis "src/app/store" importer { selectQueryParams } depuis "src/app/store/selectors/router.selectors" classe d'exportation AboutComponent { constructeur (magasin privé : Store<AppState>) { this.store.pipe(select(selectQueryParams)).subscribe(console.log) } }