Zum Inhalt springen
Blog

Robuste Vue-3-Komponenten entwickeln

2. Juni 2023 · 15 Min. Lesezeit · Ronald Blüthl

Vue ist seit einigen Jahren mein bevorzugtes Framework. Es erledigt zuverlässig seinen Job, ist einfach zu verwenden, und ich kenne es mittlerweile sehr gut. In diesem Beitrag möchte ich meinen persönlichen Ansatz für die Arbeit mit Vue 3 teilen, einen Ansatz, der Ihnen hoffentlich hilft, bessere Vue-Komponenten zu bauen.

№ 01 TypeScript

Mit Vue 3 ist TypeScript nun ein integraler Bestandteil des Frameworks (Vue 3 selbst ist in TypeScript geschrieben). Nutzen Sie Vue mit TypeScript, Ihre gesamte Codebasis wird typsicher und Sie ersparen sich viele Probleme.

№ 02 Composition API

Die Composition API ist wohl das wichtigste Konzept, das es im Vergleich zu Vue 2 zu verstehen gilt. Sie ist deutlich vielseitiger und erleichtert das Teilen von Logik und Daten. Ich verwende sie für alle neuen Vue-3-Projekte.

№ 03 script setup Syntax

Die script setup-Syntax bietet einige Vorteile: weniger Code, automatische Bereitstellung von Top-Level-Bindings, bessere TypeScript-Unterstützung. Diese werden wir verwenden.

<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

№ 04 MagicButton, props & emits

Eine eigene Button-Komponente mit props (inkl. Standardwert) und emit:

// MagicButton.vue
<script setup lang="ts">
interface Props {
  text: string
  loading: boolean
}

withDefaults(defineProps<Props>(), { loading: false })

const emit = defineEmits<{
  (event: 'click', mouseEvent: MouseEvent): void
}>()
</script>

<template>
  <button @click="(e) => emit('click', e)" :disabled="loading">
    <span v-if="loading">Loading...</span>
    <span v-else>{{ text }}</span>
  </button>
</template>

№ 05 MagicInput, v-model & ref

Eine Input-Komponente mit Zwei-Wege-Bindung:

// MagicInput.vue
<script setup lang="ts">
interface Props { modelValue: string }
defineProps<Props>()

const emit = defineEmits<{
  (event: 'update:modelValue', value: string): void
}>()
</script>

<template>
  <input :value="modelValue"
         @input="emit('update:modelValue', $event.target.value)"
         type="text" />
</template>

№ 06 ref und computed

Reaktive Daten mit ref und abgeleitete Werte mit computed:

const text = ref(props.initialValue)
const textLength = computed(() => text.value.length)

Beachten Sie, dass wir bei text als ref den Zugriff über .value benötigen, um den eigentlichen Wert zu erhalten.

№ 07 Konventionen

  • PascalCase für Komponenten, <MagicButton>
  • kebab-case für props, initial-value
  • Einfache Anführungszeichen statt doppelter
  • Datentyp ableiten lassen, wenn er offensichtlich ist
  • Keine Semikolons
  • Immer ein Props-Interface extrahieren
  • watch-Ausdrücke so weit wie möglich vermeiden

№ 08 Einweg-Datenfluss

In Vue fließen Daten nur in eine Richtung. props sind schreibgeschützt. Wenn Sie übergebene props verändern möchten, verwenden Sie ein ref und übergeben den prop-Wert als Initialwert:

interface Props { initialText: string }
const props = defineProps<Props>()
const text = ref(props.initialText)

№ 09 Objekte und Arrays nicht mutieren

Aufgrund der Natur von JavaScript-Objekten ist es technisch möglich, diese in einer Komponente zu mutieren, was sich dann auch auf die übergeordnete Komponente auswirkt. Vermeiden Sie das unbedingt. Stattdessen ein Event mit den aktualisierten Daten emittieren und die Mutation in der übergeordneten Komponente durchführen:

const props = defineProps<{ names: string[] }>()
const emit = defineEmits<{
  (event: 'change', names: string[]): void
}>()

const addName = (name: string) => {
  const updatedNames = [...props.names, name]
  emit('change', updatedNames)
}

№ 10 Schlusswort

Die Kombination aus Composition API, TypeScript und script setup ist eine wirklich elegante Art, saubere und prägnante Komponenten in Vue 3 zu schreiben. Bei mir funktioniert das hervorragend, und ich hoffe, bei Ihnen auch.

Klingt nach Ihrem Vorhaben? Prototyp um 2.900 €. Erstgespräch buchen