Vue 3 <script setup>-Tutorial
tutorial vuejs typescript | Antony Konstantinidis • | 7 Minuten
Mit der Veröffentlichung der Composition API hat auch die neue Komponentenoption setup
Einzug in Vue erhalten. Damit benötigen wir in den meisten Fällen keine anderen Optionen mehr und schreiben unsere gesamten Code innerhalb dieser Funktion. Die Idee von <script setup>
ist, dass man den unnötigen Wrapper und die anderen alten Komponentenoptionen loswerden möchte, um vereinfacht und zielgerichtet Komponenten schreiben kann.
// OldExampleComponent.vue
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
const count = ref<number>(0)
function increment() {
count.value++
}
return {
count,
increment
}
}
})
</script>
// NewExampleComponent.vue
<script setup lang="ts">
import { ref } from 'vue'
const count = ref<number>(0)
function increment() {
count.value++
}
</script>
Mit der <script setup>
-Syntax können wir kompakt und direkt unsere Komponentenlogik schreiben. Selbst ein return
-Statement wird nicht mehr benötigt. Jede Variable und Methode, die wir definieren, wird automatisch im Template zur Verfügung gestellt.
Auch importierte Daten, wie Funktionen und sogar Komponenten, können wir direkt verwenden. Komponenten müssen nicht mal mehr gesondert registriert werden:
<script setup lang="ts">
import { ref } from 'vue'
import { format } from '@/utils/currency'
import MyComponent from '@/components/MyComponent.vue'
const count = ref<number>(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">{{ format(count) }}</button>
<MyComponent />
</template>
Props und Events
Um Optionen wie props
und emits
zu deklarieren, müssen wir sogenannte Compiler-Makros verwenden, welche automatisch innerhalb von <script setup>
verfügbar sind.
<script setup lang="ts">
const props = defineProps({
msg: String
})
const emit = defineEmits(['update', 'remove'])
</script>
Die beiden Funktionen müssen nicht importiert werden und werden bei der Verarbeitung von <script setup>
weg kompiliert.
defineProps
nimmt denselben Wert an, wie die Option props
, während defineEmits
denselben Wert annimmt wie die Option emits
.
Wenn wir ohnehin schon TypeScript in unserer Anwendung verwenden, dann können wir props
und emits
auch mit einer reinen Typsyntax deklarieren:
const props = defineProps<{
msg: string
count?: number
}>()
const emit = defineEmits<{
(e: 'update', id: number): void
(e: 'remove'): void
}>()
Beide Ansätze können nicht miteinander kombiniert werden, d. h. entweder wir verwenden den Generic oder die Klammern der Funktionen, aber niemals beides gleichzeitig. Entscheiden wir uns für den TypeScript-Weg, so ist wichtig zu erwähnen, dass wir aktuell keine importierten Typen oder Interfaces verwenden können, sondern nur Typ-Literale (siehe Beispiel) oder in der selben Datei definierte Typen oder Interfaces.
Bei den Events können wir selbst die Parameter genauer spezifizieren und damit typensicheren Code schreiben.
Standardwerte für props
Oben im Beispiel haben wir die prop count
als optional gekennzeichnet, allerdings fehlt uns hier eine Möglichkeit einen Standardwert anzugeben. Aus diesem Grund existiert ein weiterer Compiler-Makro namens withDefaults
.
interface Props {
msg: string
count?: number
}
const props = withDefaults(defineProps<Props>(), {
count: 0
})
Wird withDefaults
nicht verwendet, aber eine Prop im Typen als optional gekennzeichnet, behandelt Vue diese prop
als obligatorisch.
Slots und Attribute verwenden
In der Regel werden Slots und Attribute in Komponenten direkt im Template über $slots
und $attrs
verwendet und selten bis gar nicht im script
benötigt. Falls es dennoch mal vonnöten sen sollte, stellt Vue mit useSlots
und useAttrs
entsprechende Funktionen bereit.
<script setup lang="ts">
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>
Weitere Optionen verwenden
In einigen Fällen ist es nötig, dass wir benutzerdefinierte Optionen in unseren Komponenten deklarieren. Vuelidate’s validations
Option ist da nur ein beliebtes Beispiel. Diese weiteren Optionen, zu denen auch das Setzen eines Komponentennamens über name
gehört, ist mit <script setup>
nicht möglich.
Die Lösung zu diesen Problemen ist die Verwendung eines zusätzlichen script
-Tags. Die beiden Blöcke werden bei der Verarbeitung der *.vue
-Datei dann automatisch zusammengefügt.
<script>
// executed only once
export const componentName = 'MyComponent';
export default {
name: componentName
inheritAttrs: false,
customOptions: {}
}
</script>
<script setup>
// executed for each component instance
</script>
Zugriff von außen?
Verwenden wir <script setup>
steht uns zwar alles im Template zur Verfügung, die Komponente selbst ist allerdings nach außen geschlossen. Wir können also über die Instanz einer Komponente, beispielsweise bei der Verwendung von $parent
oder Template refs, nicht auf die Eigenschaften und Funktionen, die innerhalb von <script setup>
deklariert wurden, zugreifen.
Um etwas explizit freizugeben, müssen wir ein weiteres Compiler-Makro verwenden: defineExpose
.
<script setup lang="ts">
import { ref } from 'vue'
const count = ref<number>(0)
function increment() {
count.value++
}
defineExpose({
count,
increment
})
</script>
Top-level await
In Komponenten müssen wir häufig Daten asynchron von einem Service anfragen. In <script setup>
steht uns dafür auf oberster Ebene das await
Keyword zur Verfügung.
Eine auf diese Art definierte Komponente muss mit der Suspense
-Komponente verwendet werden, damit Vue sich um die Auflösung der Asynchronität kümmern und die Komponente richtig laden kann.
// AsyncComponent.vue
<script setup>
const user = await fetch(`/users/1`).then((d) => d.json())
</script>
// ParentComponent.vue
<template>
<Suspense>
<AsyncComponent />
</Suspense>
</template>
Achtung: Bei Suspense handelt es sich derzeit allerdings noch um ein experimentelles Feature, welches nicht für produktive Anwendungen empfohlen wird.
Verfügbarkeit außerhalb von Vue 3
Solltest du nicht das große Glück haben bereits mit Vue 3 arbeiten zu dürfen, wird es dich sicher freuen zu erfahren, dass es ein fantastisches Plugin gibt, mit welchem <script setup>
sowohl in Vue 2, als auch Nuxt, Vite oder der Vue CLI zur Verfügung steht: Unplugin vue2-script-setup
Inhaltsverzeichnis
Um alle Neuigkeiten zu erfahren, abonniere hier unseren Newsletter!
Newsletter abonnierenAntony Konstantinidis