Управление состоянием своего приложения — интересная и весьма важная задача для многих приложений. Ведь от этого зависит то, насколько внятно и вменяемо будет построен пользовательский интерфейс и насколько успешным будет само приложение.
Сегодня я хотел бы рассказать об одном интересном open-source проекте, который может облегчить работу с состояниями для тех, кто решил написать или переписать свое приложение на Angular2 и думает о том, переписывать ли ему логику управления состояниями заново или стоит что-либо поискать на просторах этих ваших интернетов.
Angular2 State Machine
angular2-state-machine — это порт, с некоторыми адаптационными изменениями, javascript-state-machine на Angular2 для того, чтобы упростить переход на ng2 тех приложений, которые, так или иначе, работают с состояниями.
На данный момент существует версия на TypeScript, поскольку он, де-факто, является стандартом для ng2 приложений на данный момент.
Сама библиотека простая и небольшая, участие — приветствуется, недавно был выпущен первый релиз в npm.
Немножко кода
Установим библиотеку:
npm i angular2-state-machine --save
Дальше будем исходить из того, что у Вас уже есть рабочее ng2 приложение, пусть даже пустое, с app.component.ts.
Будем рассматривать возможности библиотеки на примере обычного светофора.
Перед тем, как начать использовать библиотеку, надо заимпортить модуль и создать саму state-machine со всеми состояниями и переходами и задать начальное состояние.
import {StateMachine, StateEvent} from './core';
let fsm = new StateMachine({
initial: 'green',
events: [
new StateEvent({
name: 'toGreen', from: ['yellow'], to: 'green'
}),
new StateEvent({
name: 'toRed', from: ['yellow'], to: 'red'
}),
new StateEvent({
name: 'toYellow', from: ['red', 'green'], to: 'yellow'
})
]
});
Здесь мы создали state-machine на основе трех состояний светофора: Зеленый, Желтый, Красный, и дали имена самим переходам на эти состояния: 'toGreen', 'toYellow', 'toRed'.
Необходимо использовать только уникальные имена событий, иначе сервис на этапе инициализации будет выдавать ошибку: «You have to use unique names for all events».
Перед тем, как идти дальше, нужно обьяснить в двух словах, что такое StateMachine и StateEvent.
StateMachine — собственно, сам сервис, который занимается переходами из состояния в состояние.
StateEvent — типизированное событие, которое описывает переходы в state-machine.
Допустим, Ваше приложение начинается с того, что запускается зеленый свет. Спустя некоторое время, должен запуститься желтый. Для того, чтобы сменить состояние светофора, необходимо сделать следующее:
fsm.fireAction('toYellow'); // Текущее состояние - Желтый свет
Также, можно узнать текущее состояние:
fsm.getCurrent() // yellow
Если машина состояний впечатляет своими масштабами и Вы, в какой-то момент времени, хотите проверить можно ли из текущего состояние перейти в другое, определенное, состояние, то можно сделать следующее:
fsm.can('toYellow') // Error 'You cannot switch to this state'
В описанном примере Вы не можете переключить на желтый свет, потому как он уже горит.
Есть и инвертированный метод, для любителей:
fsm.cannot('toYellow') // true
Также можно узнать все доступные события указанной машины состояний:
fsm.getEvents() /* [StateEvent({
name: 'toGreen', from: ['yellow'], to: 'green'
}),
StateEvent({
name: 'toRed', from: ['yellow'], to: 'red'
}),
StateEvent({
name: 'toYellow', from: ['red', 'green'], to: 'yellow'
})
]*/
Или же узнать текущее имя события на которое переход доступен:
fsm.getTransitions() // 'toYellow'
Если необходимо перейти на шаг назад:
fsm.goToPreviousState() // 'green'
Вот так вот, легко и просто, можно управлять состояниями своего приложения и не переписывать все с нуля.
Комментарии (8)
justboris
07.11.2016 01:38+3Также, было бы неплохо оформить саму библиотеку лучше:
1) Добавить служебные файлы и папки.idea
,.iml
,.DS_Store
в.gitignore
2) УбратьpeerDependencies
изpackage.json
. Они не используются в коде, а значит, не нужны.
3) Секцииmain
иtypings
изpackage.json
ведут на несуществующие файлы. Если правильно их описать, то подключать библиотеку станет чуть проще.
import {StateMachine, StateEvent} from 'angular2-state-machine';
jsfun
07.11.2016 01:59+1Согласен, надо убрать и упростить, работаем над этим, спасибо за комментарий.
Anarions
07.11.2016 12:50Не специализируюсь на фронте, поэтому может глупость спрошу, но вроде-бы есть redux для работы со state-ом? У него ещё и плюшек всяких много.
jsfun
07.11.2016 13:01Redux — управление состоянием всего приложения используя лишь один основной Store + определенное количество reducers, которые state меняют и actions, которые что-то делают — например клик юзера по блоку или загрузка данных. Именно это и является имплементацией Flux. Тогда как, моя маленькая библиотечка служит примитивным целям — просто менять состояние простого обьекта и в зависимости от состояния, приложение может что-то делать.
У Redux есть связи между reducers, Store и actions, тогда как у меня все просто:
- Создал машину состояний
- Поменял состояние
- При изменении, можно заставить приложение как-то на это отреагировать.
В конце концов, по сути, и моя либа и Redux делает одно и тоже — управляет состоянием, но уровень размаха разный.
justboris
А причем здесь Angular2?
Как видно из кода, библиотека работает с любым фреймворком, разве что больше типизации за счет TypeScript появилось.
jsfun
Изначально, я разрабатывал ее под Angular2, но она действительно достаточно проста, чтобы ее переиспользовать