angular
July 31, 2024
Использование Flux-паттерна в Angular
Flux — это архитектурный паттерн, используемый для создания одностороннего потока данных в приложениях. Он был разработан Facebook и используется для управления состоянием в приложениях, особенно когда они становятся сложными. В Angular для работы со стором можно использовать Flux-подобные библиотеки, такие как NgRx.
Основные концепции Flux
- Store: Хранит состояние приложения и логику управления этим состоянием. В Angular это может быть реализовано с помощью NgRx Store, который представляет собой реактивное хранилище для управления состоянием приложения.
- Actions: Объекты, которые описывают изменения в состоянии. Actions отправляются в стор для инициирования изменений состояния.
- Dispatcher: Центральный узел, который принимает actions и распределяет их в сторы. В NgRx это представлено метками действия, которые передаются в редукторы.
- Reducers: Чистые функции, которые принимают текущее состояние и action, затем возвращают новое состояние. В NgRx редукторы определяют, как изменяется состояние в ответ на actions.
- Selectors: Функции для получения данных из store. Они помогают избежать прямого доступа к состоянию и способствуют созданию более модульного кода.
Пример использования Flux-подхода с NgRx в Angular
1. Установка NgRx
Для начала необходимо установить необходимые пакеты NgRx:
npm install @ngrx/store @ngrx/effects @ngrx/store-devtools
2. Определение Actions
Создайте файл actions.ts для определения действий:
codeimport { createAction, props } from '@ngrx/store';
export const addTodo = createAction('[Todo List] Add Todo', props<{ todo: string }>());
export const removeTodo = createAction('[Todo List] Remove Todo', props<{ index: number }>());
3. Создание Reducers
Создайте файл reducers.ts для определения редукторов:
import { createReducer, on } from '@ngrx/store';
import { addTodo, removeTodo } from './actions';
export const initialState: string[] = [];
const _todoReducer = createReducer(
initialState,
on(addTodo, (state, { todo }) => [...state, todo]),
on(removeTodo, (state, { index }) => state.filter((_, i) => i !== index))
);
export function todoReducer(state: any, action: any) {
return _todoReducer(state, action);
}
4. Регистрация Store в модуле
Добавьте стор в корневой модуль app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';
import { todoReducer } from './reducers';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
StoreModule.forRoot({ todos: todoReducer })
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
5. Использование Store в компоненте
Теперь вы можете использовать стор в компоненте:
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { addTodo, removeTodo } from './actions';
interface AppState {
todos: string[];
}
@Component({
selector: 'app-root',
template: `
<div>
<h1>Todo List</h1>
<input #todoInput>
<button (click)="add(todoInput.value); todoInput.value=''">Add Todo</button>
<ul>
<li *ngFor="let todo of todos$ | async; let i = index">
{{ todo }}
<button (click)="remove(i)">Remove</button>
</li>
</ul>
</div>
`
})
export class AppComponent {
todos$: Observable<string[]>;
constructor(private store: Store<AppState>) {
this.todos$ = this.store.select('todos');
}
add(todo: string) {
this.store.dispatch(addTodo({ todo }));
}
remove(index: number) {
this.store.dispatch(removeTodo({ index }));
}
}