Управление состоянием является ключевым аспектом построения интерактивных приложений в Angular. Фреймворк предлагает реактивные подходы, позволяющие отслеживать и изменять состояние компонентов и сервисов.
BehaviorSubject для состоянияBehaviorSubject из RxJS хранит текущее состояние и
позволяет подписчикам получать его обновления.
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
interface AppState {
isLoggedIn: boolean;
userName: string;
}
@Injectable({ providedIn: 'root' })
export class StateService {
private stateSubject = new BehaviorSubject<AppState>({ isLoggedIn: false, userName: '' });
state$ = this.stateSubject.asObservable();
updateState(partialState: Partial<AppState>) {
this.stateSubject.next({ ...this.stateSubject.value, ...partialState });
}
}
FacadeФасад скрывает сложную логику управления состоянием, предоставляя простой API для компонентов.
@Injectable({ providedIn: 'root' })
export class UserFacade {
constructor(private stateService: StateService) {}
login(userName: string) {
this.stateService.updateState({ isLoggedIn: true, userName });
}
logout() {
this.stateService.updateState({ isLoggedIn: false, userName: '' });
}
get user$() {
return this.stateService.state$.pipe(map(state => state.userName));
}
}
Компоненты могут управлять собственным локальным состоянием с
использованием BehaviorSubject или простых переменных.
@Component({
selector: 'app-toggle',
template: `
<button (click)="toggle()">{{ isActive ? 'On' : 'Off' }}</button>
`
})
export class ToggleComponent {
private activeSubject = new BehaviorSubject<boolean>(false);
isActive$ = this.activeSubject.asObservable();
toggle() {
this.activeSubject.next(!this.activeSubject.value);
}
get isActive() {
return this.activeSubject.value;
}
}
Redux /
NgRxДля крупных приложений рекомендуется использование глобального
хранилища состояния через NgRx. Принципы включают:
Пример action и reducer:
import { createAction, createReducer, on } from '@ngrx/store';
export const login = createAction('[Auth] Login', (userName: string) => ({ userName }));
export const logout = createAction('[Auth] Logout');
export interface AuthState { userName: string | null; isLoggedIn: boolean; }
export const initialState: AuthState = { userName: null, isLoggedIn: false };
export const authReducer = createReducer(
initialState,
on(login, (state, { userName }) => ({ ...state, isLoggedIn: true, userName })),
on(logout, state => ({ ...state, isLoggedIn: false, userName: null }))
);
Эти подходы позволяют строить предсказуемую архитектуру, где изменения состояния централизованы и легко отслеживаются. Использование реактивных паттернов обеспечивает синхронизацию UI и бизнес-логики, предотвращая несогласованность данных.