Angular — это мощная платформа для создания масштабируемых и удобных в сопровождении веб-приложений. По мере усложнения приложений управление состоянием становится важнейшим аспектом разработки. NGRX — это библиотека управления состоянием для приложений Angular, которая помогает управлять сложным состоянием приложения и повышает производительность приложения.
В этой статье мы предоставим полное руководство по использованию NGRX с Angular. Мы сосредоточимся на выполнении простых операций CRUD (создание, чтение, обновление, удаление) с использованием NGRX. К концу этого руководства у вас будет четкое представление о том, как реализовать NGRX в приложении Angular и управлять состоянием предсказуемым и эффективным образом.
Оглавление
- Что такое NGRX и зачем его использовать?
- Настройка проекта Angular
- Создание магазина
- Определение действий
- Реализация редукторов
- Создание селекторов
- Диспетчерские действия
- Отображение данных в компонентах
- Обновление данных с помощью действий
- Удаление данных с помощью действий
- Заключение
1. Что такое NGRX и зачем его использовать?
NGRX — это библиотека управления состоянием, вдохновленная Redux, популярным инструментом управления состоянием в экосистеме React. Он следует принципам однонаправленного потока данных, где состояние неизменно, а изменения вносятся с помощью чистых функций. NGRX помогает централизовать состояние приложения, упрощая управление и отладку.
К основным преимуществам использования NGRX относятся:
- Предсказуемое управление состоянием: NGRX следует строгому шаблону, что упрощает понимание и поддержание состояния приложения.
- Масштабируемость. По мере роста вашего приложения NGRX предоставляет масштабируемую архитектуру, которая поддерживает организованное и эффективное управление состоянием.
- Отладка во времени: NGRX позволяет отслеживать действия и изменения состояния, делая отладку и тестирование намного более удобными.
- Совместное использование состояния между компонентами: NGRX позволяет совместно использовать состояние между компонентами, даже если они не связаны напрямую.
- Повышение производительности: NGRX оптимизирует производительность за счет уменьшения количества избыточных изменений состояния.
Теперь, когда мы понимаем преимущества использования NGRX, давайте настроим проект Angular и начнем работу с NGRX.
2. Настройка проекта Angular
Прежде чем мы начнем, убедитесь, что в вашей системе установлены Node.js и Angular CLI. Если нет, вы можете установить их, выполнив следующие команды:
npm install -g @angular/cli
Чтобы создать новый проект Angular, используйте интерфейс командной строки Angular для создания стандартного кода:
ng new ngrx-crud-example
Перейдите в только что созданный каталог проекта:
cd ngrx-crud-example
Теперь у нас есть готовый проект Angular, и мы можем приступить к установке необходимых зависимостей для NGRX.
3. Создание магазина
В NGRX хранилище — это место, где осуществляется управление состоянием приложения. Чтобы создать магазин, нам нужно установить пакет @ngrx/store
:
npm install @ngrx/store --save
Далее нам нужно определить состояние нашего приложения. В этом примере предположим, что мы создаем простое приложение для управления задачами, в котором задачи имеют идентификатор, заголовок и описание.
Создайте новый файл с именем task.model.ts
в каталоге src/app
и определите интерфейс Task
:
// src/app/task.model.ts export interface Task { id: number; title: string; description: string; }
Теперь создайте еще один файл с именем task.reducer.ts
в каталоге src/app
. Этот файл будет содержать начальное состояние нашего приложения и функцию редуктора, которая обрабатывает изменения состояния:
// src/app/task.reducer.ts import { Task } from './task.model'; export interface AppState { tasks: Task[]; } export const initialState: AppState = { tasks: [] }; export function taskReducer(state = initialState, action): AppState { switch (action.type) { default: return state; } }
В этом фрагменте кода мы определили начальное состояние нашего приложения с пустым массивом задач. Функция taskReducer
— это чистая функция, которая получает текущее состояние и действие в качестве аргументов и возвращает новое состояние на основе типа действия.
4. Определение действий
Действия в NGRX используются для описания изменений состояния в приложении. Это простые объекты JavaScript со свойством type
, описывающим выполняемое действие. Мы определим три типа действий для нашего приложения управления задачами: AddTask
, UpdateTask
и DeleteTask
.
Создайте новый файл с именем task.actions.ts
в каталоге src/app
и определите действия:
// src/app/task.actions.ts import { createAction, props } from '@ngrx/store'; import { Task } from './task.model'; export const addTask = createAction('[Task] Add Task', props<{ task: Task }>()); export const updateTask = createAction('[Task] Update Task', props<{ task: Task }>()); export const deleteTask = createAction('[Task] Delete Task', props<{ id: number }>());
Здесь мы использовали функцию createAction
из @ngrx/store
для определения наших действий. Первый аргумент createAction
— это тип действия, заключенный в квадратные скобки, чтобы указать, что оно относится к функции Task
. Второй аргумент, props
, используется для определения полезной нагрузки действия. В нашем случае действия addTask
и updateTask
ожидают объект task
, а deleteTask
ожидает id
в качестве полезной нагрузки.
5. Реализация редукторов
Теперь, когда мы определили наши действия, нам нужно реализовать редукторы, которые обрабатывают эти действия и соответствующим образом обновляют состояние.
Откройте файл task.reducer.ts
и импортируйте действия, которые мы определили ранее:
// src/app/task.reducer.ts import { Task } from './task.model'; import { addTask, updateTask, deleteTask } from './task.actions'; export interface AppState { tasks: Task[]; } export const initialState: AppState = { tasks: [] }; export function taskReducer(state = initialState, action): AppState { switch (action.type) { case addTask.type: return { ...state, tasks : [...state.tasks, action.task] }; case updateTask.type: return { ...state, tasks: state.tasks.map(task => (task.id === action.task.id ? action.task : task)) }; case deleteTask.type: return { ...state, tasks: state.tasks.filter(task => task.id !== action.id) }; default: return state; } }
В этом обновленном коде мы импортировали действия и добавили случаи в нашу функцию taskReducer
для обработки каждого типа действия. Для addTask
мы создаем новое состояние, добавляя новую задачу в массив существующих задач. Для updateTask
мы сопоставляем задачи и обновляем одну с подходящим id
. По deleteTask
отфильтровываем задачу с указанным id
.
6. Создание селекторов
Селекторы в NGRX используются для доступа к определенным частям состояния из хранилища. Они позволяют нам вычислять производные данные на основе состояния и избегать прямого доступа к состоянию.
Создайте новый файл с именем task.selectors.ts
в каталоге src/app
и определите селекторы:
// src/app/task.selectors.ts import { createSelector } from '@ngrx/store'; import { AppState } from './task.reducer'; export const selectTasks = (state: AppState) => state.tasks; export const selectTaskById = (id: number) => createSelector(selectTasks, tasks => tasks.find(task => task.id === id));
В этом фрагменте кода мы использовали функцию createSelector
из @ngrx/store
для определения наших селекторов. Селектор selectTasks
извлекает массив задач из состояния, а selectTaskById
принимает аргумент id
и возвращает задачу с соответствующим id
.
7. Диспетчерские действия
Теперь, когда мы настроили хранилище, определили действия и реализовали редюсеры и селекторы, давайте перейдем к диспетчеризации действий из наших компонентов.
Откройте файл app.component.ts
в каталоге src/app
. В этом файле мы будем отправлять действия для добавления, обновления и удаления задач.
// src/app/app.component.ts import { Component } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState } from './task.reducer'; import { addTask, updateTask, deleteTask } from './task.actions'; import { Task } from './task.model'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { tasks: Task[] = []; constructor(private store: Store<AppState>) { this.store.select('tasks').subscribe(tasks => this.tasks = tasks); } addNewTask() { const newTask: Task = { id: this.tasks.length + 1, title: 'New Task', description: 'This is a new task.' }; this.store.dispatch(addTask({ task: newTask })); } updateTask(task: Task) { const updatedTask: Task = { ...task, title: 'Updated Task', description: 'This task has been updated.' }; this.store.dispatch(updateTask({ task: updatedTask })); } deleteTask(id: number) { this.store.dispatch(deleteTask({ id })); } }
В этом фрагменте кода мы импортировали необходимые модули и зависимости, включая Store
из @ngrx/store
, наши действия и интерфейс Task
. Мы также определили методы для добавления, обновления и удаления задач и отправили соответствующие действия с помощью метода store.dispatch()
.
8. Отображение данных в компонентах
Теперь, когда мы можем отправлять действия, давайте создадим пользовательский интерфейс для отображения наших задач и предоставления пользователям возможности добавлять, обновлять и удалять их.
Откройте файл app.component.html
в каталоге src/app
и обновите его следующим образом:
<!-- src/app/app.component.html --> <div *ngFor="let task of tasks" class="task"> <h3>{{ task.title }}</h3> <p>{{ task.description }}</p> <button (click)="updateTask(task)">Update</button> <button (click)="deleteTask(task.id)">Delete</button> </div> <button (click)="addNewTask()">Add New Task</button>
В этом HTML-шаблоне мы используем директиву Angular *ngFor
для циклического перебора задач и отображения их заголовков и описаний. Мы также добавляем кнопки для обновления и удаления каждой задачи и кнопку для добавления новой задачи.
9. Обновление данных с помощью действий
При нажатии кнопки «Обновить» для задачи вызывается метод updateTask()
, который отправляет действие updateTask
с обновленным объектом задачи.
10. Удаление данных с помощью действий
Когда для задачи нажимается кнопка «Удалить», вызывается метод deleteTask()
, который отправляет действие deleteTask
с id
задачи.
11. Заключение
В этой статье мы рассмотрели, как использовать NGRX в приложении Angular для управления состоянием и выполнения простых операций CRUD. Мы настроили хранилище, определили действия, реализовали редьюсеры и создали селекторы для доступа к определенным частям состояния. Мы также узнали, как отправлять действия из компонентов для изменения состояния.
NGRX предоставляет надежное и масштабируемое решение для управления состоянием приложений, особенно полезное для больших и сложных приложений. Используя NGRX, вы можете сделать свои приложения Angular более удобными в сопровождении, предсказуемыми и эффективными.
Обладая этими знаниями, вы теперь можете начать интегрировать NGRX в свои собственные проекты Angular и создавать более мощные и хорошо структурированные приложения.