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)
}
}