Простая машина состояний для VueJS

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.


Недавно я наткнулся на интересное обсуждение на Full Stack Radio — Bulding Better UI Components with State Machines. Речь шла о том, что концепция машины состояний может помочь при разработке компонентов Vue. Я начал просматривать готовые решения, но они оказались не столь просты, и мне захотелось сделать более простую реализацию, о которой я и хочу рассказать в этой статье. Статья может оказаться полезной не только для тех кто использует Vue, но и для пользователей Angular, React и т.д., а также для программистов других «конфессий».

В обсуждении затрагивалась тема, близкая всем, кто писал компоненты. Представьте. что вы пишете компонент, который обращается за данными, и вам надо отобразить спиннер на то время, пока запрос выполняется. Обычно в таких случаях вы создаете логическую переменную isLoading. Изначально isLoading = false, а перед тем, как запросить данные вы присваиваете переменной isLoading значение true. После того, как данные пришли вы опять присваиваете ей значение false. Видимость спиннера привязана к isLoading.

Этот подход отлично работает. Но компонент редко бывает столь простым. И в ходе работы приходится создавать еще логические переменные, которые хранят разные состояния. Проблема в том, что если у вас одна переменная состояния, она порождает два состояния, а две логические переменные уже четыре состояния, три — восемь и т.д. И беда в том, программист может ошибиться и не обработать какие-то состояния, в которые может прийти система. А это приводит к ошибке. Кроме того довольно сложно понимать такой компонент и приходится плодить условия.

Ответ — машина состояний. Принцип простой — вы описываете состояния в которых может быть система, и переходы между состояниями. Имея такую машину можно избежать многих ошибок, а также декларативно определять состояния системы.

На эту тему довольно много статей (например Finite State Machines in Vue, но большинство из них после краткой теории рекомендуют подключить одну из готовых библиотек. Например davidkpiano/xstate.

Мне xstate показался излишне громоздким и захотелось попробовать свой велосипед. К тому же это отличный повод разобрать новый, для меня, паттерн.

Вот тут код с которым можно поиграть — State machine with Vue, version 2. А тут сырая версия, со слегка отличающимся подходом — State machine with Vue, version 1.
Отталкивался я от статьи State Machines.

Итак машина состояний:

class StateMachine {
    constructor (initialState, transitions) {
        this.state = initialState
        this.transitions = transitions
    }
    transition (nextState, method, params) {
  	const transitionsArray = this.transitions[this.state]	
        if(transitionsArray.indexOf(nextState) === -1) return this.state
        if(method) method(...params)
        this.state = nextState
        return this.state
    }
}

Инициализируем ее так:

const machine = new StateMachine('idle', {
    idle: ['waitingConfirmation'],
    waitingConfirmation: ['idle','waitingData'],
    waitingData: ['dataReady', 'dataProblem'],
    dataReady: ['waitingConfirmation'],
    dataProblem: ['waitingConfirmation']
})

В методах компонента создаем функцию перехода:

transition(nextState, method = null, params = []) {
    this.machineState = machine.transition(nextState, method, params)
}

В событиях сразу пишем куда хотим перейти:

@click=“transition('waitingConfirmation')"

Если надо при этом вызвать метод компонента пишем так:

@click="transition('waitingData', getData, [222])”

Второй параметр — метод компонента который надо вызвать с этим переходом.
Третий параметр — массив переменных для этого метода.

Внутри методов вызов такой:

this.transition('dataReady')

Я специально не стал скрывать кнопки с помощью v-if, просто пока делаю цвет их шрифта сереньким. Зато видно, что нажатие на них не срабатывает, если машина не разрешает.

В целом все работает, решение очень легкое. И главное удалось декларативно описать работу компонента. Я сам уже почти готов применить данный подход в реальном приложении, но хотелось бы понять за и против этого подхода, и послушать советы от более умудренных опытом специалистов.
Источник: https://habr.com/ru/post/482250/


Интересные статьи

Интересные статьи

Я давно знаком с Битрикс24, ещё дольше с 1С-Битрикс и, конечно же, неоднократно имел дела с интернет-магазинами которые работают на нём. Да, конечно это дорого, долго, местами неуклюже...
Если Вы разрабатываете более-менее сложный программный продукт, то Вам должна быть знакома ситуация, когда системные (end-to-end) тесты по тем или иным причинам автоматизировать не ...
Мне было необходимо делать 2 раза в сутки бэкап сайта на «1С-Битрикс: Управление сайтом» (файлов и базы mysql) и хранить историю изменений за 90 дней. Сайт расположен на VDS под уп...
Кому предназначена данная статья Данная статья может быть интересна системным администраторам, перед которыми вставала задача создать сервис «одноразовых» рабочих мест. Пролог В отдел ИТ со...
В Челябинске проходят митапы системных администраторов Sysadminka, и на последнем из них я делал доклад о нашем решении для работы приложений на 1С-Битрикс в Kubernetes. Битрикс, Kubernetes, Сep...