[Easy] Vue3 Neue Features
1. What are the new features in Vue 3?
Welche neuen Features hat Vue 3?
Vue 3 hat viele neue Features und Verbesserungen eingeführt, darunter:
Wichtigste neue Features
- Composition API: Neue Schreibweise für Komponenten
- Teleport: Komponenten an andere DOM-Positionen rendern
- Fragment: Komponenten können mehrere Wurzelknoten haben
- Suspense: Behandlung des Ladens asynchroner Komponenten
- Mehrere v-model: Unterstützung mehrerer v-model
- Bessere TypeScript-Unterstützung
- Performance-Optimierung: Kleinere Bundle-Größe, schnellere Rendergeschwindigkeit
2. Teleport
Was ist Teleport?
Definition: Teleport erlaubt es uns, den Inhalt einer Komponente an einer anderen Stelle im DOM-Baum zu rendern, ohne die logische Struktur der Komponente zu ändern.
Anwendungsszenarien
Gängige Szenarien: Modal, Tooltip, Notification und andere Komponenten, die im body gerendert werden müssen
Klicken Sie hier, um das Teleport-Beispiel zu erweitern
<template>
<div>
<button @click="showModal = true">Modal öffnen</button>
<!-- Teleport verwenden, um Modal im body zu rendern -->
<Teleport to="body">
<div v-if="showModal" class="modal">
<div class="modal-content">
<h2>Modal-Titel</h2>
<p>Modal-Inhalt</p>
<button @click="showModal = false">Schließen</button>
</div>
</div>
</Teleport>
</div>
</template>
<script setup>
import { ref } from 'vue';
const showModal = ref(false);
</script>
Vorteile
- Löst z-index-Probleme: Modal wird im body gerendert, unabhängig von Elternkomponenten-Stilen
- Behält logische Struktur bei: Komponentenlogik bleibt am ursprünglichen Ort, nur die DOM-Position ist anders
- Bessere Wartbarkeit: Modal-bezogener Code ist in der Komponente zentralisiert
3. Fragment (Mehrere Wurzelknoten)
Was ist Fragment?
Definition: Vue 3 erlaubt Komponenten mit mehreren Wurzelknoten, ohne sie in ein einzelnes Element einwickeln zu müssen. Dies ist ein implizites Fragment, es wird keine <Fragment>-Tag wie in React benötigt.
Vue 2 vs Vue 3
Vue 2: Einzelner Wurzelknoten erforderlich
<!-- Vue 2: Muss in einzelnes Element eingewickelt werden -->
<template>
<div>
<h1>Titel</h1>
<p>Inhalt</p>
</div>
</template>
Vue 3: Mehrere Wurzelknoten möglich
<!-- Vue 3: Mehrere Wurzelknoten möglich -->
<template>
<h1>Titel</h1>
<p>Inhalt</p>
</template>
Warum brauchen wir Fragment?
In Vue 2 mussten Komponenten einen einzelnen Wurzelknoten haben, was Entwickler oft zwang, zusätzliche Wrapper-Elemente (wie <div>) hinzuzufügen, die:
- Semantisches HTML brechen: Bedeutungslose Wrapper-Elemente hinzufügen
- DOM-Ebenen erhöhen: Stilselektoren und Performance beeinflussen
- Stilkontrolle erschweren: Stile des zusätzlichen Wrapper-Elements müssen behandelt werden
Anwendungsszenarien
Szenario 1: Semantische HTML-Struktur
<template>
<!-- Kein zusätzliches Wrapper-Element nötig -->
<header>
<h1>Seitentitel</h1>
</header>
<main>
<p>Hauptinhalt</p>
</main>
<footer>
<p>Fußzeile</p>
</footer>
</template>
Szenario 2: Listenelement-Komponente
<!-- ListItem.vue -->
<template>
<li class="item-title">{{ title }}</li>
<li class="item-description">{{ description }}</li>
</template>
<script setup>
defineProps({
title: String,
description: String,
});
</script>
Szenario 3: Bedingte Darstellung mehrerer Elemente
<template>
<div v-if="showHeader" class="header">Titel</div>
<div v-if="showContent" class="content">Inhalt</div>
<div v-if="showFooter" class="footer">Fußzeile</div>
</template>
Attributvererbung (Attribute Inheritance)
Bei Komponenten mit mehreren Wurzelknoten ändert sich das Verhalten der Attributvererbung.
Einzelner Wurzelknoten: Attribute werden automatisch an das Wurzelelement vererbt
<!-- Elternkomponente -->
<MyComponent class="custom-class" id="my-id" />
<!-- Kindkomponente (einzelner Wurzelknoten) -->
<template>
<div>Inhalt</div>
</template>
<!-- Render-Ergebnis -->
<div class="custom-class" id="my-id">Inhalt</div>
Mehrere Wurzelknoten: Attribute werden nicht automatisch vererbt, manuelle Zuweisung erforderlich
<!-- Elternkomponente -->
<MyComponent class="custom-class" id="my-id" />
<!-- Kindkomponente (mehrere Wurzelknoten) -->
<template>
<div>Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
</template>
<!-- Render-Ergebnis: Attribute werden nicht automatisch vererbt -->
<div>Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
Lösung: $attrs verwenden, um Attribute manuell zu binden
<!-- Kindkomponente -->
<template>
<div v-bind="$attrs">Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
</template>
<!-- Render-Ergebnis -->
<div class="custom-class" id="my-id">Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
inheritAttrs: false zur Steuerung des Vererbungsverhaltens:
<script setup>
defineOptions({
inheritAttrs: false, // Automatische Vererbung deaktivieren
});
</script>
<template>
<div v-bind="$attrs">Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
</template>
Fragment vs React Fragment
| Eigenschaft | Vue 3 Fragment | React Fragment |
|---|---|---|
| Syntax | Implizit (keine Tags) | Explizit (<Fragment> oder <>) |
| Key-Attribut | Nicht erforderlich | Bei Bedarf <Fragment key={...}> |
| Attributvererbung | Manuelle Behandlung | Keine Attributunterstützung |
Vue 3:
<!-- Vue 3: Implizites Fragment -->
<template>
<h1>Titel</h1>
<p>Inhalt</p>
</template>
React:
// React: Explizites Fragment
function Component() {
return (
<>
<h1>Titel</h1>
<p>Inhalt</p>
</>
);
}
Hinweise
- Attributvererbung: Bei mehreren Wurzelknoten werden Attribute nicht automatisch vererbt,
$attrsmuss manuell verwendet werden - Style-Scoping: Bei mehreren Wurzelknoten werden
scoped-Stile auf alle Wurzelknoten angewendet - Logisches Wrapping: Wenn logisch ein Wrapper benötigt wird, sollte weiterhin ein einzelner Wurzelknoten verwendet werden
<!-- ✅ Gute Praxis: Logisch ein Wrapper nötig -->
<template>
<div class="card">
<h2>Titel</h2>
<p>Inhalt</p>
</div>
</template>
<!-- ⚠️ Vermeiden: Mehrere Wurzelknoten ohne Notwendigkeit -->
<template>
<h2>Titel</h2>
<p>Inhalt</p>
<!-- Wenn diese Elemente logisch zusammengehören, sollten sie eingewickelt werden -->
</template>
4. Suspense
Was ist Suspense?
Definition: Suspense ist eine eingebaute Komponente zum Behandeln des Ladezustands asynchroner Komponenten.
Grundlegende Verwendung
<template>
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>Laden...</div>
</template>
</Suspense>
</template>
<script setup>
import { defineAsyncComponent } from 'vue';
const AsyncComponent = defineAsyncComponent(() =>
import('./AsyncComponent.vue')
);
</script>
Anwendungsszenarien
-
Laden asynchroner Komponenten
<Suspense>
<AsyncUserProfile :userId="userId" />
<template #fallback>
<UserProfileSkeleton />
</template>
</Suspense> -
Asynchrones Laden von Daten
<script setup>
const data = await fetchData(); // await im setup verwenden
</script>
5. Multiple v-model
Mehrere v-model
Definition: Vue 3 erlaubt Komponenten die Verwendung mehrerer v-model, wobei jedes v-model einem anderen Prop entspricht.
Vue 2 vs Vue 3
Vue 2: Nur ein v-model
<!-- Vue 2: Nur ein v-model -->
<CustomInput v-model="value" />
Vue 3: Mehrere v-model möglich
<!-- Vue 3: Mehrere v-model möglich -->
<CustomForm
v-model:username="username"
v-model:email="email"
v-model:password="password"
/>
Implementierungsbeispiel
<!-- CustomForm.vue -->
<template>
<div>
<input
:value="username"
@input="$emit('update:username', $event.target.value)"
/>
<input :value="email" @input="$emit('update:email', $event.target.value)" />
<input
:value="password"
@input="$emit('update:password', $event.target.value)"
/>
</div>
</template>
<script setup>
defineProps(['username', 'email', 'password']);
defineEmits(['update:username', 'update:email', 'update:password']);
</script>
6. Common Interview Questions
Häufige Interviewfragen
Frage 1: Anwendungsszenarien von Teleport
Erklären Sie, wann Teleport verwendet werden sollte.
Klicken Sie hier, um die Antwort zu sehen
Szenarien für Teleport:
-
Modal-Dialog
<Teleport to="body">
<Modal v-if="showModal" />
</Teleport>- Löst z-index-Probleme
- Unabhängig von Elternkomponenten-Stilen
-
Tooltip
<Teleport to="body">
<Tooltip v-if="showTooltip" />
</Teleport>- Vermeidet Verstecken durch overflow der Elternkomponente
-
Notification
<Teleport to="#notifications">
<Notification v-for="msg in messages" :key="msg.id" />
</Teleport>- Einheitliche Verwaltung der Benachrichtigungsposition
Kein Teleport nötig bei:
- Allgemeinem Inhalt
- Komponenten ohne besondere DOM-Positionsanforderungen
Frage 2: Vorteile von Fragment
Erklären Sie die Vorteile von mehreren Wurzelknoten in Vue 3.
Klicken Sie hier, um die Antwort zu sehen
Vorteile:
-
Reduziert unnötige DOM-Elemente
<!-- Vue 2: Zusätzliches div nötig -->
<template>
<div>
<header>...</header>
<main>...</main>
</div>
</template>
<!-- Vue 3: Kein zusätzliches Element nötig -->
<template>
<header>...</header>
<main>...</main>
</template> -
Besseres semantisches HTML
- Keine bedeutungslosen Wrapper-Elemente wegen Vue-Einschränkungen
- Behält die Semantik der HTML-Struktur bei
-
Flexiblere Stilkontrolle
- Keine Behandlung von Wrapper-Element-Stilen nötig
- Reduziert CSS-Selektor-Komplexität
-
Weniger DOM-Ebenen
- Flacherer DOM-Baum, bessere Performance
- Reduziert Browser-Rendering-Kosten
-
Bessere Wartbarkeit
- Saubererer Code ohne zusätzliche Wrapper-Elemente
- Klarere Komponentenstruktur
Frage 3: Fragment-Attributvererbungsproblem
Erklären Sie das Verhalten der Attributvererbung bei Komponenten mit mehreren Wurzelknoten. Wie löst man das?
Klicken Sie hier, um die Antwort zu sehen
Problem:
Bei Komponenten mit mehreren Wurzelknoten werden von der Elternkomponente übergebene Attribute (wie class, id usw.) nicht automatisch an einen Wurzelknoten vererbt.
Beispiel:
<!-- Elternkomponente -->
<MyComponent class="custom-class" id="my-id" />
<!-- Kindkomponente (mehrere Wurzelknoten) -->
<template>
<div>Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
</template>
<!-- Render-Ergebnis: Attribute nicht automatisch vererbt -->
<div>Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
Lösungen:
$attrsverwenden, um Attribute manuell zu binden
<!-- Kindkomponente -->
<template>
<div v-bind="$attrs">Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
</template>
<!-- Render-Ergebnis -->
<div class="custom-class" id="my-id">Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
inheritAttrs: falsezur Steuerung des Vererbungsverhaltens
<script setup>
defineOptions({
inheritAttrs: false, // Automatische Vererbung deaktivieren
});
</script>
<template>
<div v-bind="$attrs">Erster Wurzelknoten</div>
<div>Zweiter Wurzelknoten</div>
</template>
- Selektives Binden bestimmter Attribute
<template>
<div :class="$attrs.class">Erster Wurzelknoten</div>
<div :id="$attrs.id">Zweiter Wurzelknoten</div>
</template>
Wichtige Punkte:
- Einzelner Wurzelknoten: Attribute werden automatisch vererbt
- Mehrere Wurzelknoten: Attribute werden nicht automatisch vererbt, manuelle Behandlung nötig
- Mit
$attrskann auf alle nicht inpropsdefinierten Attribute zugegriffen werden
Frage 4: Fragment vs React Fragment
Vergleichen Sie Vue 3 Fragment und React Fragment.
Klicken Sie hier, um die Antwort zu sehen
Hauptunterschiede:
| Eigenschaft | Vue 3 Fragment | React Fragment |
|---|---|---|
| Syntax | Implizit (keine Tags) | Explizit (<Fragment> oder <>) |
| Key-Attribut | Nicht erforderlich | Bei Bedarf <Fragment key={...}> |
| Attributvererbung | Manuelle Behandlung ($attrs) | Keine Attributunterstützung |
Vue 3:
<!-- Vue 3: Implizites Fragment, direkt mehrere Wurzelknoten -->
<template>
<h1>Titel</h1>
<p>Inhalt</p>
</template>
React:
// React: Explizites Fragment, Tags erforderlich
function Component() {
return (
<>
<h1>Titel</h1>
<p>Inhalt</p>
</>
);
}
// Oder mit Fragment
import { Fragment } from 'react';
function Component() {
return (
<Fragment>
<h1>Titel</h1>
<p>Inhalt</p>
</Fragment>
);
}
Vorteilsvergleich:
- Vue 3: Kompaktere Syntax, keine zusätzlichen Tags
- React: Expliziter, Key-Attribut möglich
Frage 5: Verwendung von Suspense
Implementieren Sie ein Beispiel mit Suspense zum Laden einer asynchronen Komponente.
Klicken Sie hier, um die Antwort zu sehen
<template>
<Suspense>
<template #default>
<AsyncUserProfile :userId="userId" />
</template>
<template #fallback>
<div class="loading">
<Spinner />
<p>Benutzerdaten werden geladen...</p>
</div>
</template>
</Suspense>
</template>
<script setup>
import { ref } from 'vue';
import { defineAsyncComponent } from 'vue';
import Spinner from './Spinner.vue';
const userId = ref(1);
// Asynchrone Komponente definieren
const AsyncUserProfile = defineAsyncComponent(() =>
import('./UserProfile.vue')
);
</script>
Fortgeschrittene Verwendung: Fehlerbehandlung
<template>
<Suspense @resolve="onResolve" @reject="onReject">
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>Laden...</div>
</template>
</Suspense>
</template>
<script setup>
const onResolve = () => {
console.log('Komponente erfolgreich geladen');
};
const onReject = (error) => {
console.error('Komponente konnte nicht geladen werden:', error);
};
</script>
7. Best Practices
Beste Praktiken
Empfohlene Vorgehensweisen
<!-- 1. Modal mit Teleport -->
<Teleport to="body">
<Modal v-if="showModal" />
</Teleport>
<!-- 2. Mehrere Wurzelknoten semantisch halten -->
<template>
<header>...</header>
<main>...</main>
<footer>...</footer>
</template>
<!-- 3. Asynchrone Komponenten mit Suspense -->
<Suspense>
<AsyncComponent />
<template #fallback>
<LoadingSpinner />
</template>
</Suspense>
<!-- 4. Mehrere v-model mit eindeutigen Namen -->
<CustomForm v-model:username="username" v-model:email="email" />
Zu vermeidende Praktiken
<!-- 1. Teleport nicht übermäßig verwenden -->
<Teleport to="body">
<div>Allgemeiner Inhalt</div> <!-- ❌ Nicht nötig -->
</Teleport>
<!-- 2. Struktur nicht für mehrere Wurzelknoten aufbrechen -->
<template>
<h1>Titel</h1>
<p>Inhalt</p>
<!-- ⚠️ Wenn logisch ein Wrapper nötig ist, einzelnen Wurzelknoten verwenden -->
</template>
<!-- 3. Fehlerbehandlung bei Suspense nicht ignorieren -->
<Suspense>
<AsyncComponent />
<!-- ⚠️ Ladefehler sollten behandelt werden -->
</Suspense>
8. Interview Summary
Interview-Zusammenfassung
Schnelle Merkhilfe
Hauptneuerungen von Vue 3:
- Composition API: Neue Schreibweise für Komponenten
- Teleport: Komponenten an andere DOM-Positionen rendern
- Fragment: Unterstützung mehrerer Wurzelknoten
- Suspense: Behandlung des Ladens asynchroner Komponenten
- Mehrere v-model: Unterstützung mehrerer v-model-Bindungen
Anwendungsszenarien:
- Modal/Tooltip →
Teleport - Semantisches HTML →
Fragment - Asynchrone Komponenten →
Suspense - Formularkomponenten → Mehrere
v-model
Beispielantwort für Interviews
F: Welche sind die wichtigsten neuen Features von Vue 3?
"Vue 3 hat viele neue Features eingeführt, darunter: 1) Composition API, bietet eine neue Schreibweise mit besserer Logikorganisation und Wiederverwendbarkeit; 2) Teleport, erlaubt das Rendern von Komponenteninhalten an anderen DOM-Baum-Positionen, häufig verwendet für Modal, Tooltip usw.; 3) Fragment, Komponenten können mehrere Wurzelknoten haben ohne zusätzliche Wrapper-Elemente; 4) Suspense, behandelt den Ladezustand asynchroner Komponenten; 5) Mehrere v-model, unterstützt mehrere v-model-Bindungen pro Komponente; 6) Bessere TypeScript-Unterstützung und Performance-Optimierung. Diese Features machen Vue 3 leistungsfähiger und flexibler bei gleichzeitiger Abwärtskompatibilität."
F: Was sind die Anwendungsszenarien von Teleport?
"Teleport wird hauptsächlich in Szenarien verwendet, in denen Komponenten an anderen DOM-Baum-Positionen gerendert werden müssen. Gängige Szenarien sind: 1) Modal-Dialoge, die im body gerendert werden, um z-index-Probleme zu vermeiden; 2) Tooltips, die nicht durch overflow der Elternkomponente versteckt werden; 3) Benachrichtigungen mit einheitlicher Positionsverwaltung. Der Vorteil von Teleport ist, dass die logische Komponentenstruktur unverändert bleibt und nur die DOM-Renderposition geändert wird, was sowohl Stilprobleme löst als auch die Wartbarkeit des Codes beibehält."