Verwenden von XSTATE fĂŒr VueJS





Ein kleines Beispiel fĂŒr die Verwendung der XState- Bibliothek von David Khourshid zur deklarativen Beschreibung der Logik einer VueJS 2-Komponente. XState ist eine sehr fortschrittliche Bibliothek zum Erstellen und Verwenden von Zustandsautomaten in JS. Keine schlechte Hilfe bei der schwierigen Aufgabe, Webanwendungen zu erstellen.



Vorgeschichte



In meinem letzten Artikel habe ich kurz beschrieben, warum Zustandsautomaten (Zustandsautomaten) benötigt werden und eine einfache Implementierung fĂŒr die Arbeit mit Vue. Mein Fahrrad hatte nur Staaten und die StaatserklĂ€rung sah so aus:



{
    idle: ['waitingConfirmation'],
    waitingConfirmation: ['idle','waitingData'],
    waitingData: ['dataReady', 'dataProblem'],
    dataReady: [‘idle’],
    dataProblem: ['idle']
}


TatsĂ€chlich war es eine AufzĂ€hlung von ZustĂ€nden, und fĂŒr jeden wurde eine Reihe möglicher ZustĂ€nde beschrieben, in die das System gehen kann. Die Anwendung "sagt" einfach zur Zustandsmaschine - ich möchte in einen solchen Zustand gehen, wenn möglich, geht die Maschine in den gewĂŒnschten Zustand.



Dieser Ansatz funktioniert, es gibt jedoch Unannehmlichkeiten. Zum Beispiel, wenn eine SchaltflĂ€che in einem anderen Zustand einen Übergang in verschiedene ZustĂ€nde einleiten soll. Wir mĂŒssen die Bedingungen umzĂ€unen. Anstelle von DeklarativitĂ€t bekommen wir Brei.



Nachdem ich die Theorie an Videos von YouTube studiert hatte, wurde klar, dass Ereignisse notwendig und wichtig sind. Diese Art von ErklÀrung wurde in meinem Kopf geboren:



{
  idle: {
    GET: 'waitingConfirmation',
  },
  waitingConfirmation: {
    CANCEL: 'idle',
    CONFIRM: 'waitingData'
  },
  waitingData: {
    SUCCESS: 'dataReady',
    FAILURE: 'dataProblem'
  },
  dataReady: {
    REPEAT: 'idle'
  },
  dataProblem: {
    REPEAT: 'idle'
  }
}


Und dies ist bereits sehr Àhnlich der Beschreibung von ZustÀnden in der XState-Bibliothek. Nachdem ich das Dock genauer gelesen hatte, beschloss ich, mein selbstgemachtes Fahrrad in die Scheune zu stellen und zu einem Markenfahrrad zu wechseln.



VUE + XState



Die Installation ist sehr einfach. Lesen Sie das Dokument. Nach der Installation fĂŒgen wir XState in die Komponente ein:



import {Machine, interpret} from ‘xstate’


Wir erstellen ein Auto basierend auf dem Deklarationsobjekt:



const myMachine = Machine({
    id: 'myMachineID',
    context: {
      /* some data */
    },
    initial: 'idle',
    states: {
        idle: {
          on: {
            GET: 'waitingConfirmation',
          }
        },
        waitingConfirmation: {
          on: {
            CANCEL: 'idle',
            CONFIRM: 'waitingData'
          }
        },
        waitingData: {
          on: {
            SUCCESS: 'dataReady',
            FAILURE: 'dataProblem'
          },
        },
        dataReady: {
          on: {
            REPEAT: 'idle'
          }
        },
        dataProblem: {
          on: {
            REPEAT: 'idle'
          }
        }
    }
})


Es ist klar, dass es ZustĂ€nde wie "Leerlauf", "WartebestĂ€tigung" gibt ... und Ereignisse in Großbuchstaben GET, CANCEL, CONFIRM ...



Die Maschine selbst funktioniert nicht, Sie mĂŒssen mit der Interpretationsfunktion einen Dienst daraus erstellen. Wir werden einen Link zu diesem Dienst in unserem Bundesstaat und gleichzeitig einen Link zum aktuellen Status platzieren:



data: {
    toggleService: interpret(myMachine),
    current: myMachine.initialState,
}


Der Dienst muss gestartet werden - start (), und außerdem muss angegeben werden, dass beim Übergang des Status der Wert von current aktualisiert wird:



mounted() {
    this.toggleService
        .onTransition(state => {
            this.current = state
         })
        .start();
    }


Wir fĂŒgen den Methoden die Sendefunktion hinzu und steuern damit die Maschine - um Ereignisse an sie zu senden:



methods: {
   send(event) {
      this.toggleService.send(event);
   },
  

} 


Dann ist alles einfach. Senden Sie eine Veranstaltung, indem Sie einfach anrufen:



this.send(‘SUCCESS’)


Finden Sie den aktuellen Status heraus:



this.current.value


ÜberprĂŒfen Sie, ob sich die Maschine in einem bestimmten Zustand befindet:



this.current.matches(‘waitingData')




Alles zusammen:



Vorlage
<div id="app">
  <h2>XState machine with Vue</h2>
  <div class="panel">
    <div v-if="current.matches('idle')">
      <button @click="send('GET')">
        <span>Get data</span>
      </button>
    </div>
    <div v-if="current.matches('waitingConfirmation')">
      <button @click="send('CANCEL')">
        <span>Cancel</span>
      </button>
      <button @click="getData">
        <span>Confirm get data</span>
      </button>
    </div>
    <div v-if="current.matches('waitingData')" class="blink_me">
      loading ...
    </div>
    <div v-if="current.matches('dataReady')">
      <div class='data-hoder'>
        {{ text }}
      </div>
      <div>
        <button @click="send('REPEAT')">
          <span>Back</span>
        </button>
      </div>
    </div>
    <div v-if="current.matches('dataProblem')">
      <div class='data-hoder'>
        Data error!
      </div>
      <div>
        <button @click="send('REPEAT')">
          <span>Back</span>
        </button>
      </div>
    </div>
  </div>
  <div class="state">
    Current state: <span class="state-value">{{ current.value }}</span>
  </div>
</div>




Js
const { Machine, interpret } = XState

const myMachine = Machine({
    id: 'myMachineID',
    context: {
      /* some data */
    },
    initial: 'idle',
    states: {
        idle: {
          on: {
            GET: 'waitingConfirmation',
          }
        },
        waitingConfirmation: {
          on: {
            CANCEL: 'idle',
            CONFIRM: 'waitingData'
          }
        },
        waitingData: {
          on: {
            SUCCESS: 'dataReady',
            FAILURE: 'dataProblem'
          },
        },
        dataReady: {
          on: {
            REPEAT: 'idle'
          }
        },
        dataProblem: {
          on: {
            REPEAT: 'idle'
          }
        }
    }
	})



new Vue({
  el: "#app",
  data: {
  	text: '',
  	toggleService: interpret(myMachine),
    current: myMachine.initialState,
  },
  computed: {

  },
  mounted() {
    this.toggleService
        .onTransition(state => {
          this.current = state
        })
        .start();
  },
  methods: {
    send(event) {
      this.toggleService.send(event);
    },
    getData() {
      this.send('CONFIRM')
    	requestMock()
      .then((data) => {       
      	this.text = data.text   
      	this.send('SUCCESS')
      })
      .catch(() => this.send('FAILURE'))
    },

  }
})

function randomInteger(min, max) {
  let rand = min + Math.random() * (max + 1 - min)
  return Math.floor(rand);
}

function requestMock() {
  return new Promise((resolve, reject) => {
  	const randomValue = randomInteger(1,2)
  	if(randomValue === 2) {
    	let data = { text: 'Data received!!!'}
      setTimeout(resolve, 3000, data)
    }
    else {
    	setTimeout(reject, 3000)
    }
  })
}




Und natĂŒrlich kann all dies auf jsfiddle.net berĂŒhrt werden



Visualizer



XState bietet ein großartiges Tool, den Visualizer . Sie können das Diagramm Ihres bestimmten Autos sehen. Und nicht nur zu schauen, sondern auch auf Ereignisse zu klicken und ÜbergĂ€nge zu machen. So sieht unser Beispiel aus:







Ergebnis



XState funktioniert hervorragend mit VueJS. Dies vereinfacht die Arbeit der Komponente und ermöglicht es Ihnen, unnötigen Code zu entfernen. Die Hauptsache ist, dass Sie mit der Deklaration der Maschine die Logik schnell verstehen können. Dieses Beispiel ist einfach, aber ich habe es bereits an einem komplexeren Beispiel fĂŒr ein Arbeitsprojekt versucht. Der Flug ist normal.



In diesem Artikel habe ich nur die grundlegendsten Funktionen der Bibliothek verwendet, da ich noch genug davon habe, aber die Bibliothek enthÀlt viele weitere interessante Funktionen:



  • Bewachte ÜbergĂ€nge
  • Aktionen (Ein-, Ausstieg, Übergang)
  • Erweiterter Status (Kontext)
  • Orthogonale (parallele) ZustĂ€nde
  • Hierarchische (verschachtelte) ZustĂ€nde
  • Geschichte


Und es gibt auch Ă€hnliche Bibliotheken, zum Beispiel Robot. Hier ist ein Vergleich des Vergleichs von Zustandsautomaten: XState vs. Roboter . Wenn Sie sich also fĂŒr ein Thema interessieren, haben Sie etwas zu tun.



All Articles