
Recentemente, deparei-me com uma discussão interessante sobre o Full Stack Radio -
Bulding Better UI Components com State Machines . O ponto era que o conceito de uma máquina de estado poderia ajudar no desenvolvimento dos componentes do Vue. Comecei a procurar soluções prontas, mas elas não eram tão simples e eu queria fazer uma implementação mais simples, sobre a qual quero falar neste artigo. O artigo pode ser útil não apenas para quem usa o Vue, mas também para usuários do Angular, React etc., bem como para programadores de outras “denominações”.
A discussão abordou um tópico próximo a todos que escreveram os componentes. Imagine. que você está escrevendo um componente que solicita dados e é necessário exibir o girador enquanto a consulta está em execução. Normalmente, nesses casos, você cria uma variável booleana isLoading. Inicialmente, isLoading = false, e antes de solicitar dados, você define a variável isLoading como true. Após a chegada dos dados, você os define novamente como false. A visibilidade do girador está vinculada a isLoading.
Essa abordagem funciona muito bem. Mas o componente raramente é tão simples. E no decorrer do trabalho, ainda é necessário criar variáveis lógicas que armazenam estados diferentes. O problema é que, se você tiver uma variável de estado, ela gera dois estados e duas variáveis lógicas já têm quatro estados, três - oito, etc. E o problema é que o programador pode cometer um erro e não processar nenhum estado em que o sistema possa entrar. E isso leva a um erro. Além disso, é bastante difícil entender esse componente e é necessário criar condições.
A resposta é uma máquina de estado. O princípio é simples - você descreve os estados em que o sistema pode estar e as transições entre os estados. Ter uma máquina dessas pode evitar muitos erros, além de determinar declarativamente o estado do sistema.
Existem muitos artigos sobre esse assunto (por exemplo,
Máquinas de Estado Finito no Vue , mas a maioria deles, após uma breve teoria, recomenda conectar uma das bibliotecas prontas. Por exemplo,
davidkpiano / xstate .
Eu pensei que o xstate era muito pesado e queria experimentar minha bicicleta. Além disso, esse é um ótimo motivo para criar um novo padrão para mim.
Aqui está o código para jogar -
Máquina de estado com Vue, versão 2 . E aqui está a versão bruta, com uma abordagem um pouco diferente -
Máquina de estado com Vue, versão 1 .
Comecei no artigo
State Machines .
Então a máquina de estado:
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 } }
Inicialize assim:
const machine = new StateMachine('idle', { idle: ['waitingConfirmation'], waitingConfirmation: ['idle','waitingData'], waitingData: ['dataReady', 'dataProblem'], dataReady: ['waitingConfirmation'], dataProblem: ['waitingConfirmation'] })
Nos métodos do componente, crie uma função de transição:
transition(nextState, method = null, params = []) { this.machineState = machine.transition(nextState, method, params) }
Nos eventos, escrevemos imediatamente para onde queremos ir:
@click=“transition('waitingConfirmation')"
Se você precisar chamar o método component ao mesmo tempo, escreva isto:
@click="transition('waitingData', getData, [222])”
O segundo parâmetro é o método do componente que deve ser chamado com essa transição.
O terceiro parâmetro é uma matriz de variáveis para este método.
Dentro dos métodos, a chamada é:
this.transition('dataReady')
Eu deliberadamente não ocultei os botões com v-if, por enquanto, deixei a cor da fonte cinza. Mas é claro que clicar neles não funcionará se a máquina não permitir.
Em geral, tudo funciona, a solução é muito fácil. E o mais importante, conseguimos descrever declarativamente a operação do componente. Eu mesmo estou quase pronto para aplicar essa abordagem em um aplicativo real, mas gostaria de entender os prós e contras dessa abordagem e ouvir conselhos de especialistas mais experientes.