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.