Este artículo le brindará una comprensión profunda del administrador de estado NgRx de Angular y le presentará cómo usar NgRx. ¡Espero que le resulte útil!
NgRx es una solución de arquitectura Redux para la gestión del estado global en aplicaciones Angular. [Tutoriales relacionados recomendados: "tutorial angular"]
@ngrx/store: módulo de gestión de estado global
@ngrx/effects: Manejo de efectos secundarios
@ngrx/store-devtools: herramienta de depuración del navegador, debe depender de la extensión Redux Devtools
@ngrx/schematics: herramienta de línea de comandos para generar rápidamente archivos NgRx
@ngrx/entity: Mejore la eficiencia de los desarrolladores en la operación de datos en Reducer
@ngrx/router-store: sincronizar el estado de enrutamiento con la tienda global
1. Descargar NgRx
npm install @ngrx/store @ngrx/effects @ngrx/entity @ngrx/router-store @ngrx/store-devtools @ngrx/schematics
2. Configurar la CLI de NgRx
ng config cli.defaultCollection @ngrx/schematics
// angular.json "cli": { "defaultCollection": "@ngrx/schematics" }
3. Crear tienda
ng g store State --root --module app.module.ts --statePath store --stateInterface AppState
4. Crear acción
ng g action store/actions/counter --skipTests
importar {createAction} desde "@ngrx/store" exportar incremento constante = crearAcción("incremento") exportar decremento constante = createAction("decremento")
5. Crear reductor
ng g reducer store/reducers/counter --skipTests --reducers=../index.ts
importar {createReducer, on} desde "@ngrx/store" importar {decremento, incremento} desde "../acciones/contra.acciones" exportar const counterFeatureKey = "contador" Estado de la interfaz de exportación { contar: número } exportar const estado inicial: Estado = { contar: 0 } exportar reductor constante = crearReducer( estado inicial, on(incremento, estado => ({ recuento: estado.recuento + 1 })), on(decremento, estado => ({ recuento: estado.recuento - 1 })) )
6. Crear selector
ng g selector store/selectors/counter --skipTests
importar {createFeatureSelector, createSelector} desde "@ngrx/store" importar {counterFeatureKey, Estado} desde "../reducers/counter.reducer" importar {AppState} desde ".." exportar const selectCounter = createFeatureSelector<AppState, State>(counterFeatureKey) exportar const selectCount = createSelector(selectCounter, estado => estado.count)
7. La clase de componente desencadena la acción y obtiene el estado.
importar {seleccionar, Tienda} desde "@ngrx/store" importar {Observable} desde "rxjs" importar {AppState} desde "./store" importar {disminución, incremento} desde "./store/actions/counter.actions" importar {selectCount} desde "./store/selectors/counter.selectors" exportar clase AppComponent { recuento: observable <número> constructor(tienda privada: Tienda<AppState>) { this.count = this.store.pipe(select(selectCount)) } incremento() { this.store.dispatch(incremento()) } decremento() { this.store.dispatch(decremento()) } }
8. Estado de visualización de la plantilla de componentes
<botón (clic)="increment()">+</botón> <span>{{ recuento | asíncrono }}</span> <botón (clic)="decremento()">-</botón>
1. Utilice el envío en el componente para pasar parámetros al activar la Acción, y los parámetros eventualmente se colocarán en el objeto Acción.
this.store.dispatch(incremento({ recuento: 5 }))
2. Al crear la función Action Creator, obtenga los parámetros y especifique el tipo de parámetro.
importar {createAction, props} desde "@ngrx/store" exportar incremento constante = createAction("incremento", accesorios<{ recuento: número }>())
exportar declarar accesorios de función<P extiende objeto>(): Accesorios<P>;
3. Obtenga parámetros a través del objeto Acción en Reducer.
exportar reductor constante = crearReducer( estado inicial, on(incremento, (estado, acción) => ({ recuento: estado.recuento + acción.recuento })) )
metaReducer es un enlace entre Acción -> Reductor, que permite a los desarrolladores preprocesar la Acción (llamada antes de las llamadas a la función Reductor ordinaria).
función de depuración (reductor: ActionReducer <cualquier>): ActionReducer <cualquier> { función de retorno (estado, acción) { reductor de retorno (estado, acción) } } exportar const metaReducers: MetaReducer<AppState>[] =!environment.production ?[depurar] : []
Requisito: agregue un botón a la página. Después de hacer clic en el botón, espere un segundo para que el valor aumente.
1. Agregue un botón para incrementar el valor asíncrono en la plantilla del componente. Después de hacer clic en el botón, se ejecuta el método increment_async
.
<botón (hacer clic)="increment_async()">async</button>
2. Agregue el método increment_async
a la clase de componente y active la Acción para realizar operaciones asincrónicas en el método.
incremento_async() { this.store.dispatch(increment_async()) }
3. Agregue una Acción para realizar operaciones asincrónicas en el archivo de Acción.
exportar const increment_async = createAction("increment_async")
4. Crear efecto, recibir acción y realizar efectos secundarios, y continuar desencadenando acción
ng g effect store/effects/counter --root --module app.module.ts --skipTests
La función Efecto la proporciona el módulo @ngrx/effects, por lo que las dependencias del módulo relevantes deben importarse en el módulo raíz.
importar {Inyectable} desde "@angular/core" importar {Acciones, crearEfecto, ofType} desde "@ngrx/effects" importar {incremento, increment_async} desde "../actions/counter.actions" importar {mergeMap, mapa} desde "rxjs/operators" importar {temporizador} desde "rxjs" // crear efecto // Se usa para crear efectos, Efecto se usa para realizar efectos secundarios. // Pase la función de devolución de llamada al llamar al método y devuelva el objeto Observable en la función de devolución de llamada. El objeto Acción que se activará después de que se ejecuten los efectos secundarios // El valor de retorno de la función de devolución de llamada continúa devolviéndose dentro de createEffect. método, y el valor de retorno final se almacena en En las propiedades de la clase Efecto // Después de crear una instancia de la clase Efecto, NgRx se suscribirá a las propiedades de la clase Efecto. Cuando se completen los efectos secundarios, obtendrá el objeto Acción que se activará. y desencadenar la acción. //Comportamiento // Cuando un componente activa una Acción, el Efecto necesita recibir la Acción a través del servicio Acciones, por lo que en la clase Efecto, el objeto de instancia de la clase de servicio Acciones se inyecta en la clase Efecto a través del parámetro constructor // La instancia. El objeto de la clase de servicio Acciones es Observable. Cuando se activa una Acción, el objeto de Acción en sí se emitirá como un flujo de datos // ofType. // Filtrar el objeto de acción de destino. // El parámetro es la función Action Creator de la Acción de destino // Si el objeto de Acción de destino no se filtra, el flujo de datos no continuará enviándose esta vez // Si el objeto de Acción de destino se filtra, el objeto de Acción continuará enviándose como un flujo de datos @Injectable() clase de exportación CounterEffects { constructor(acciones privadas: Acciones) { // this.loadCount.subscribe(console.log) } loadCount = crearEffect(() => { devolver this.actions.pipe( de tipo (increment_async), mergeMap(() => temporizador(1000).pipe(mapa(() => incremento({ recuento: 10 })))) ) }) }
1. Descripción general
La entidad se traduce como entidad y la entidad es un dato de la colección.
NgRx proporciona objetos adaptadores de entidad. Bajo los objetos adaptadores de entidad, se proporcionan varios métodos para operar entidades en la colección. El propósito es mejorar la eficiencia de los desarrolladores que operan entidades.
2. Núcleo
1. EntityState: interfaz de tipo de entidad
/* { identificadores: [1, 2], entidades: { 1: {id: 1, título: "Hola Angular" }, 2: {id: 2, título: "Hola NgRx" } } } */ El estado de la interfaz de exportación extiende EntityState<Todo> {}
2. createEntityAdapter: crear un objeto adaptador de entidad
3. EntityAdapter: interfaz de tipo de objeto de adaptador de entidad
exportar adaptador constante: EntityAdapter<Todo> = createEntityAdapter<Todo>() // Obtener el estado inicial. Puede pasar parámetros de objeto o no. // {ids: [], entidades: {}} exportar const estadoinicial: Estado = adaptador.getInitialState()
3. Método de instancia
https://ngrx.io/guide/entity/adapter#adapter-collection-methods
4. Selector
// selectTotal obtiene el número de elementos de datos // selectAll obtiene todos los datos y los presenta en forma de matriz // selectEntities obtiene la colección de entidades y la presenta en forma de diccionario // selectIds obtiene la colección de id y presenta en forma de matriz const { selectIds, selectEntities, selectAll, selectTotal } = adaptor .getSelectors();
exportar const selectTodo = createFeatureSelector<AppState, State>(todoFeatureKey) exportar const seleccionarTodos = crearSelector(seleccionarTodo, seleccionarTodo)
1. Sincronizar el estado de enrutamiento
1) Introducir módulos
importar { StoreRouterConnectingModule } desde "@ngrx/router-store" @NgModule({ importaciones: [ StoreRouterConnectingModule.forRoot() ] }) exportar clase AppModule {}
2) Integrar el estado de ruta en la Tienda
importar * como desdeRouter desde "@ngrx/router-store" interfaz de exportación AppState { enrutador: fromRouter.RouterReducerState } exportar reductores constantes: ActionReducerMap<AppState> = { enrutador: fromRouter.routerReducer }
2. Cree un selector para obtener el estado de ruta
// enrutador.selectores.ts importar {createFeatureSelector} desde "@ngrx/store" importar {AppState} desde ".." importar {RouterReducerState, getSelectors} desde "@ngrx/router-store" const selectRouter = createFeatureSelector<AppState, RouterReducerState>( "enrutador" ) constante de exportación { // Obtener información relacionada con la ruta actual (parámetros de ruta, configuración de ruta, etc.) seleccione Ruta actual, // Obtener el contenido después del número # en la barra de direcciones selectFragment, // Obtener parámetros de consulta de enrutamiento selectQueryParams, // Obtener un parámetro de consulta específico selectQueryParam('nombre') seleccioneQueryParam, // Obtener parámetros de enrutamiento dinámico selectRouteParams, // Obtener un parámetro de enrutamiento dinámico específico selectRouteParam('nombre') seleccione parámetro de ruta, // Obtener datos personalizados de ruta selectRouteData, // Obtener la dirección de acceso real de la ruta selectUrl } = getSelectores(seleccionarEnrutador)
// inicio.componente.ts importar {seleccionar, Tienda} desde "@ngrx/store" importar {AppState} desde "src/app/store" importar {selectQueryParams} desde "src/app/store/selectors/router.selectors" clase de exportación Acerca del componente { constructor(tienda privada: Tienda<AppState>) { this.store.pipe(select(selectQueryParams)).subscribe(console.log) } }