Vue (ausgesprochen /vjuː/, wie das englische view) ist ein Javascript-Framework mit einer niedrigen Einstiegshürde – vor allem wenn man sich vorher schon mit Javascript, HTML und CSS befasst hat.
Die Würfel-Komponente die wir in diesem Kapitel anschauen, habe ich für eine Werkstatt gebaut. Die Schüler*Innen sollten nicht alle am selben Posten arbeiten. Mit dem Würfel konnten sie ihren nächsten Posten selbst bestimmen.
Playground
Unter https://sfc.vuejs.org gibt es einen Vue-Playground für Single-File-Components. Das Standard-Beispiel verwendet die neue Composition-API (mit dem Setup-Skript). Diese steht ab Vue 3 zur Verfügung. Allerdings funktioniert die alte Schreibweise, wie sie in Vue 2 verwendet wird, immer noch.
Vue-Komponente
Wir zerlegen nun die Vue-Würfel-Komponente. Dabei verwenden wir die Vue 2-Schreibweise, welche den Javascript-Teil in klar definierte Unterbereiche teilt. Wir programmieren zuerst die Grundfunktionalität, ohne Schnick-Schnack:
1
HTML
Im sogenannten Template-Teil definieren wir die HTML-Struktur der Komponente. Folgende Punkte gilt es zu beachten:
- das Template-Tag muss genau ein HTML-Element beinhalten – nicht mehrere!
tossedin den geschweiften Klammern ist ein Platzhalter für den berechneten Wurf- mittels
@click="toss"binden wir die Methodetossan das Klick-Event desdiv-Elementes
vue
<template>
<div class="dice" @click="toss">
{{ tossed }}
</div>
</template>Der Template-Teil einer Vue-Komponente besteht also aus HTML-Syntax, Platzhaltern, sowie speziellen Vue-Attributen die zum Binden von Daten und Methoden verwendet werden. Mehr dazu im offiziellen Guide.
JavaScript
Nach dem Template-Teil folgt der Javascript-Teil wo die Funktionalität des SFC als Javascript-Module exportiert wird:
vue
<script>
export default {
name: "SimpleDice",
data: function () {
return {
tossed: 0,
};
},
created: function () {
this.toss();
},
methods: {
toss: function () {
this.tossed = Math.ceil(Math.random() * 6);
},
},
};
</script>- data
- die Eigenschaften der Komponente mit ihren Startwerten als Funktion
- wir definieren die Variable
tossedmit Startwert 0 - created
- ist ein Hook der ausgeführt wird sobald die Komponente erstellt wird
- wir würfeln ein erstes mal
- methods
- ein Objekt von Funktionen die wir aufrufen können
- wir definieren die
toss-Methode, welche eine Zufallszahl berechnet und das Ergebnis in der Eigenschafttossedspeichert.
Es gibt weitere Hooks, ebenso wie berechnete Werte (computed) und überwachte Eigenschaften (watchers). Mehr dazu im offiziellen Guide.
CSS
Im style-Element lässt sich die Komponente mit CSS-Regeln gestalten. Durch das optionale scoped-Attribut erreichen wir, dass diese Regeln nur für diese Komponente gelten und die anderen HTML-Elemente der Webseite nicht tangieren.
vue
<style scoped>
div.dice {
padding: 10px;
border: 1px solid black;
margin: auto;
width: 50px;
text-align: center;
cursor: pointer;
}
</style>Wir versehen das div-Element um den Würfel mit einer Fütterung, einem Rahmen, zentrieren das Ganze, fixiieren die Breite, zentrieren die Zahl und setzen den Cursor damit man merkt dass da etwas klickbares ist.
Beispiel
einfach
Setzt man die 3 oben beschriebenen Teile zusammen und speichert alles als vue-Datei, so erhält man eine einsetzbare Vue-Komponente:
6
vue
<template>
<div class="dice" @click="toss">
{{ tossed }}
</div>
</template>
<script>
export default {
name: "SimpleDice",
data: function () {
return {
tossed: 0,
};
},
created: function () {
this.toss();
},
methods: {
toss: function () {
this.tossed = Math.ceil(Math.random() * 6);
},
},
};
</script>
<style scoped>
div.dice {
padding: 10px;
border: 1px solid black;
margin: auto;
width: 50px;
text-align: center;
cursor: pointer;
}
</style>ausgebaut
Der Würfel soll wie ein Würfel aussehen. Deshalb baue ich Bilder ein die über eine berechnete Eigenschaft image_tossed an das src-Attribut des img-Elements im Template gebunden werden.
Des weiteren stelle ich sicher, dass nicht 2x nacheinander dieselbe Zahl gewürfelt werden kann. (Ich weiss, dass ist keine gute Würfelsimulation!)
Schlussendlich füge ich ein transition-Element hinzu. Damit kann der Bildwechsel beim Wurf als Aus- und Ein-Blendung dargestellt werden. Dazu braucht das img-Element auch einen key der sich je Bild unterscheidet und es werden einige zusätzliche CSS-Regeln benötigt.
Der Würfel sieht jetzt wie folgt aus:
vue
<template>
<div class="dice">
<transition name="fade" mode="out-in">
<img @click="toss()" :key="tossed" :src="image_tossed" />
</transition>
</div>
</template>
<script>
import Image1 from "./dices/1.svg";
import Image2 from "./dices/2.svg";
import Image3 from "./dices/3.svg";
import Image4 from "./dices/4.svg";
import Image5 from "./dices/5.svg";
import Image6 from "./dices/6.svg";
export default {
name: "Dice",
data: function () {
return {
tossed: 0,
images: [Image1, Image2, Image3, Image4, Image5, Image6],
};
},
created: function () {
this.toss();
},
computed: {
image_tossed: function () {
return this.images[this.tossed - 1];
},
},
methods: {
toss: function () {
let newToss = Math.ceil(Math.random() * 6);
while (this.tossed == newToss) {
newToss = Math.ceil(Math.random() * 6);
}
this.tossed = newToss;
},
},
};
</script>
<style scoped>
.dice {
height: 100px;
margin: 20px;
}
.dice > img {
height: 100%;
margin: 0 auto;
display: block;
cursor: pointer;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>