Este artigo lhe dará uma compreensão profunda do gerenciador de estado do Angular, NgRx, e apresentará como usar o NgRx. Espero que seja útil para você!
NgRx é uma solução de arquitetura Redux para gerenciamento global de estado em aplicações Angular. [Tutoriais relacionados recomendados: "tutorial angular"]
@ngrx/store: módulo de gerenciamento de estado global
@ngrx/effects: Lidando com efeitos colaterais
@ngrx/store-devtools: ferramenta de depuração do navegador, precisa contar com a extensão Redux Devtools
@ngrx/schematics: ferramenta de linha de comando para gerar arquivos NgRx rapidamente
@ngrx/entity: Melhore a eficiência dos desenvolvedores na operação de dados no Redutor
@ngrx/router-store: Sincronize o status do roteamento com o armazenamento global
1. Baixe NgRx
npm install @ngrx/store @ngrx/effects @ngrx/entity @ngrx/router-store @ngrx/store-devtools @ngrx/schematics
2. Configurar CLI NgRx
ng config cli.defaultCollection @ngrx/schematics
// angular.json "cli": { "defaultCollection": "@ngrx/esquemas" }
3. Criar loja
ng g store State --root --module app.module.ts --statePath store --stateInterface AppState
4. Crie ação
ng g action store/actions/counter --skipTests
importar {createAction} de "@ngrx/store" exportar const incremento = createAction("incremento") exportar const decremento = createAction("decremento")
5. Criar Redutor
ng g reducer store/reducers/counter --skipTests --reducers=../index.ts
importar {createReducer, on} de "@ngrx/store" importar {decremento, incremento} de "../actions/counter.actions" exportar const contadorFeatureKey = "contador" interface de exportação Estado { contagem: número } exportar const estadoinicial: Estado = { contagem: 0 } exportar const redutor = createReducer( estado inicial, on (incremento, estado => ({ contagem: estado.contagem + 1 })), on (decremento, estado => ({ contagem: estado.contagem - 1 })) )
6. Criar seletor
ng g selector store/selectors/counter --skipTests
importar {createFeatureSelector, createSelector} de "@ngrx/store" importar { counterFeatureKey, State } de "../reducers/counter.reducer" importar {AppState} de ".." exportar const selectCounter = createFeatureSelector<AppState, State>(counterFeatureKey) exportar const selectCount = createSelector(selectCounter, state => state.count)
7. Classe de componente aciona ação e obtém status
importar { select, Store } de "@ngrx/store" importar {Observável} de "rxjs" importar {AppState} de "./store" importar {decremento, incremento} de "./store/actions/counter.actions" importar { selectCount } de "./store/selectors/counter.selectors" classe de exportação AppComponent { contagem: observável<número> construtor(loja privada: Store<AppState>) { this.count = this.store.pipe(select(selectCount)) } incremento() { this.store.dispatch(incremento()) } decremento() { this.store.dispatch(decremento()) } }
8. Status de exibição do modelo de componente
<button (clique)="incremento()">+</button> <span>{{ contagem | assíncrono }}</span> <button (click)="decremento()">-</button>
1. Use despacho no componente para passar parâmetros ao acionar a Ação, e os parâmetros serão eventualmente colocados no objeto Ação.
this.store.dispatch(incremento({ contagem: 5 }))
2. Ao criar a função Action Creator, obtenha os parâmetros e especifique o tipo de parâmetro.
importar {createAction, props} de "@ngrx/store" exportar const incremento = createAction("incremento", adereços<{ contagem: número }>())
exportar declarar função props<P estende objeto>(): Props<P>;
3. Obtenha parâmetros através do objeto Action no Redutor.
exportar const redutor = createReducer( estado inicial, on (incremento, (estado, ação) => ({ contagem: estado.contagem + ação.contagem })) )
metaReducer é um gancho entre Ação -> Redutor, permitindo aos desenvolvedores pré-processar Ação (chamada antes das chamadas de função comuns do Redutor).
função debug(redutor: ActionReducer<qualquer>): ActionReducer<qualquer> { função de retorno (estado, ação) { redutor de retorno (estado, ação) } } exportar const metaReducers: MetaReducer<AppState>[] = !environment.production ?[depurar] : []
Requisito: Adicione um botão à página Após clicar no botão, aguarde um segundo para que o valor aumente.
1. Adicione um botão para incremento de valor assíncrono no modelo de componente. Após clicar no botão, o método increment_async
é executado.
<button (click)="increment_async()">assíncrono</button>
2. Adicione o método increment_async
à classe do componente e acione a Action para realizar operações assíncronas no método.
incremento_async() { this.store.dispatch(increment_async()) }
3. Adicione uma ação para executar operações assíncronas no arquivo de ação.
exportar const increment_async = createAction("increment_async")
4. Criar Efeito, receber Ação e realizar efeitos colaterais, e continuar a desencadear Ação
ng g effect store/effects/counter --root --module app.module.ts --skipTests
A função Effect é fornecida pelo módulo @ngrx/effects, portanto, as dependências relevantes do módulo precisam ser importadas no módulo raiz.
importar {Injetável} de "@angular/core" importar {Ações, createEffect, ofType} de "@ngrx/effects" importar {incremento, increment_async} de "../actions/counter.actions" importar {mergeMap, map} de "rxjs/operadores" importar {temporizador} de "rxjs" //criaEfeito // Usado para criar Efeito, Efeito é usado para realizar efeitos colaterais. // Passa a função de retorno de chamada ao chamar o método e retorna o objeto Observable na função de retorno de chamada O objeto Action a ser acionado após a execução dos efeitos colaterais // O valor de retorno da função de retorno de chamada continua a ser retornado dentro de createEffect. método, e o valor de retorno final é armazenado nas propriedades da classe Effect // Após instanciar a classe Effect, o NgRx se inscreverá nas propriedades da classe Effect. Quando os efeitos colaterais forem concluídos, ele obterá o objeto Action a ser acionado. e acione a ação. //Ações // Quando um componente dispara uma Action, o Effect precisa receber a Action através do serviço Actions, portanto na classe Effect, o objeto de instância da classe de serviço Actions é injetado na classe Effect através do parâmetro construtor. objeto da classe de serviço Actions é Observable Object, quando uma Action é acionada, o próprio objeto Action será emitido como um fluxo de dados // ofType. // Filtre o objeto Action alvo. // O parâmetro é a função Action Creator da Action alvo // Se o objeto Action alvo não for filtrado, o fluxo de dados não continuará a ser enviado desta vez // Se o objeto Action alvo for filtrado, o objeto Action continuará a ser enviado como um fluxo de dados @Injectable() classe de exportação CounterEffects { construtor(ações privadas: Ações) { //this.loadCount.subscribe(console.log) } loadCount = createEffect(() => { retorne isto.actions.pipe( ofType(increment_async), mergeMap(() => timer(1000).pipe(map(() => incremento({ contagem: 10 })))) ) }) }
1. Visão geral
Entidade é traduzida como entidade e entidade é um dado na coleção.
NgRx fornece objetos adaptadores de entidade. Nos objetos adaptadores de entidade, são fornecidos vários métodos para entidades operacionais na coleção. O objetivo é melhorar a eficiência das entidades operacionais dos desenvolvedores.
2. Núcleo
1. EntityState: interface do tipo de entidade
/* { IDs: [1, 2], entidades: { 1: {id: 1, título: "Olá Angular" }, 2: {id: 2, título: "Olá NgRx" } } } */ estado da interface de exportação estende EntityState<Todo> {}
2. createEntityAdapter: Criar objeto adaptador de entidade
3. EntityAdapter: interface de tipo de objeto adaptador de entidade
exportar adaptador const: EntityAdapter<Todo> = createEntityAdapter<Todo>() // Obtenha o estado inicial Você pode passar parâmetros de objeto ou não. exportar const estadoinicial: Estado = adaptador.getInitialState()
3. Método de instância
https://ngrx.io/guide/entity/adapter#adapter-collection-methods
4. Seletor
// selectTotal obtém o número de itens de dados // selectAll obtém todos os dados e os apresenta na forma de um array // selectEntities obtém a coleção de entidades e a apresenta na forma de um dicionário // selectIds obtém a coleção de id e apresenta na forma de uma matriz const { selectIds, selectEntities, selectAll, selectTotal } = adaptador .getSelectors();
export const selectTodo = createFeatureSelector<AppState, State>(todoFeatureKey) export const selectTodos = createSelector(selectTodo, selectAll)
1. Sincronize o status do roteamento
1) Introduzir módulos
importar { StoreRouterConnectingModule } de "@ngrx/router-store" @NgModule({ importações: [ StoreRouterConnectingModule.forRoot() ] }) exportar classe AppModule {}
2) Integrar o status de roteamento na Loja
importar * como fromRouter de "@ngrx/router-store" interface de exportação AppState { roteador: fromRouter.RouterReducerState } exportar redutores const: ActionReducerMap<AppState> = { roteador: fromRouter.routerReducer }
2. Crie um seletor para obter o status do roteamento
// roteador.seletores.ts importar {createFeatureSelector} de "@ngrx/store" importar {AppState} de ".." importar { RouterReducerState, getSelectors } de "@ngrx/router-store" const selectRouter = createFeatureSelector<AppState, RouterReducerState>( "roteador" ) exportar const{ // Obtém informações relacionadas à rota atual (parâmetros de roteamento, configuração de roteamento, etc.) selecione Rota Atual, // Obtém o conteúdo após o número # na barra de endereço selectFragment, // Obtém parâmetros de consulta de roteamento selectQueryParams, // Obtém um parâmetro de consulta específico selectQueryParam('name') selectQueryParam, // Obtém parâmetros de roteamento dinâmico selectRouteParams, // Obtenha um parâmetro de roteamento dinâmico específico selectRouteParam('name') selectRouteParam, // Obtém dados personalizados da rota selectRouteData, // Obtém o endereço de acesso real da rota selectUrl } = getSelectors(selectRouter)
//home.component.ts importar { select, Store } de "@ngrx/store" importar {AppState} de "src/app/store" importar { selectQueryParams } de "src/app/store/selectors/router.selectors" exportar classe AboutComponent { construtor(loja privada: Store<AppState>) { this.store.pipe(select(selectQueryParams)).subscribe(console.log) } }