Template-Syntax-Rendering

In diesem Kapitel lernst du, die Template-Syntax von Vue zu verwenden, um JS-Daten in HTML zu rendern, sodass die Blog-Startseite eine Liste von Artikelkarten anzeigt.


Interpolationsausdruck {{ }}

Der Interpolationsausdruck ist die grundlegendste Datenbindungsmethode in Vue.

Er "fügt" den Wert einer JS-Variable in das HTML ein. Die Syntax sind doppelte geschweifte Klammern, die den Variablennamen umschließen.

Beispiel

<script setup>
const blogTitle = 'EXAMPLE Frontend Notes'
const author = 'Xiao Ming'
</script>

<template>
  <h1>{{ blogTitle }}</h1>
  <p>Autor: {{ author }}</p>
  <p>Aktuelle Zeit: {{ new Date().toLocaleDateString() }}</p>
</template>

Die Seite wird Folgendes rendern:

EXAMPLE 前端笔记
作者:小明
当前时间:2024/5/15

In die geschweiften Klammern kannst du jeden JS-Ausdruck schreiben: Variablen, Operationen, ternäre Ausdrücke, Funktionsaufrufe - alles ist möglich, aber du kannst keine Anweisungen einfügen (wie z. B.if、for)。

Der Interpolationsausdruck ersetzt nur den Text innerhalb des Tags, nicht das Tag selbst. Zum Beispiel,

{{ content }}
in
das Tag selbst ist nicht betroffen.


Attributbindung v-bind (Kurzschreibweise :)

Interpolationsausdrücke können nur für Tag-Inhalte verwendet werden, nicht für HTML-Attribute.

Um JS-Variablen in Attributen zu verwenden, musst du diev-bindDirektive verwenden.

Beispiel

<script setup>
const coverUrl = '/images/vue-cover.png'
const linkUrl = '/post/1'
const isActive = true
</script>

<template>
  <!-- Vollständige Syntax: v-bind:attribute="variable" -->
  <img v-bind:src="coverUrl" v-bind:alt="Artikelcover">

  <!-- Kurzschreibweise: direkt :attribute="variable" verwenden -->
  <a :href="linkUrl">Ganzen Artikel lesen</a>

  <!-- Dynamische Klasse: Objektsyntax verwenden -->
  <div :class="{ active: isActive, 'text-bold': true }">
Dieser Text hat sowohl die Klasse active als auch die Klasse text-bold.
  </div>
</template>

Die Doppelpunkt-Kurzschreibweiseist die gebräuchlichste Syntax; in der Praxis verwendet man fast niev-bind:den vollständigen Namen.


Listen-Rendering v-for

Die Blog-Startseite muss mehrere Artikel anzeigen. Ein einzelner Artikel ist ein Objekt, und mehrere Artikel bilden ein Objekt-Array.

v-forDu kannst über das Array iterieren und für jedes Element entsprechendes HTML generieren.

Beispiel

<script setup>
// Verwende ein JS-Objekt-Array, um Artikeldaten zu simulieren (wird später geändert, um aus einer JSON-Datei zu laden)
const articles = [
  {
    id: 1,
title: 'Vollständiger Leitfaden für den Einstieg in Vue3',
summary: 'Lerne die Vue3 Composition API von Grund auf und behandle Kernkonzepte wie ref, reactive, computed.',
    date: '2024-05-10',
    category: 'Vue',
    cover: '/images/vue.png'
  },
  {
    id: 2,
title: 'Asynchrone Programmierung in JavaScript erklärt',
summary: 'Verstehe Promise, async/await, Event-Loop und Microtask-Queue in einem Artikel.',
    date: '2024-05-08',
    category: 'JavaScript',
    cover: '/images/js.png'
  },
  {
    id: 3,
title: 'CSS Grid Layout in der Praxis',
summary: 'Komplexe responsive Layouts lassen sich mit CSS Grid einfach umsetzen, ohne die Einschränkungen von float und flexbox.',
    date: '2024-05-05',
    category: 'CSS',
    cover: '/images/css.png'
  }
]
</script>

<template>
  <div class="article-list">
    <!-- v-for="item in array" :key="eindeutige Kennung" -->
    <div v-for="article in articles" :key="article.id" class="card">
      <img :src="article.cover" :alt="article.title">
      <div class="card-body">
        <span class="category">{{ article.category }}</span>
        <h3>{{ article.title }}</h3>
        <p>{{ article.summary }}</p>
        <span class="date">{{ article.date }}</span>
      </div>
    </div>
  </div>
</template>

<style scoped>
.article-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 24px;
  margin-top: 20px;
}

.card {
  background: #fff;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0,0,0,0.08);
  transition: transform 0.2s;
}

.card:hover {
  transform: translateY(-4px);
}

.card img {
  width: 100%;
  height: 180px;
  object-fit: cover;
}

.card-body {
  padding: 16px;
}

.category {
  display: inline-block;
  padding: 2px 10px;
  background: #E8EEF5;
  color: #427DB8;
  border-radius: 12px;
  font-size: 12px;
}

.card-body h3 {
  margin: 10px 0 8px;
  font-size: 18px;
}

.card-body p {
  color: #666;
  font-size: 14px;
  line-height: 1.6;
}

.date {
  display: block;
  margin-top: 10px;
  font-size: 12px;
  color: #999;
}
</style>

Die Bedeutung des key-Attributs

:keyEr ist ein unverzichtbarer Begleiter von v-for und teilt Vue die Identität jedes Elements mit.

Wenn sich die Reihenfolge des Arrays ändert (z. B. Einfügen, Löschen, Sortieren), verwendet Vue den key, um zu bestimmen, welche DOM-Knoten aktualisiert werden müssen und welche wiederverwendet werden können.

Wert von keyKonsequenz
Eindeutige ID (empfohlen)Verfolgt jedes Element korrekt und aktualisiert effizient
Array-IndexKann bei Einfügen/Löschen zu Zustandsverwirrung führen (z. B. werden Inhalte von Eingabefeldern vertauscht)
Kein KeyDie Konsole gibt eine Warnung aus; Vue verwendet standardmäßig die Strategie der "In-Place-Aktualisierung", die eine schlechte Leistung hat.

Gib v-for immer einen eindeutigen und stabilen key; verwende nicht index als key. Das ist eine der wichtigsten Gewohnheiten in der Vue-Entwicklung.


Bedingtes Rendern v-if / v-else

Wenn du unterschiedliche Inhalte unter unterschiedlichen Bedingungen anzeigen musst, verwende diev-if-Familie von Direktiven.

Beispiel

<script setup>
import { ref } from 'vue'

const articles = ref([]) // Artikelliste (leeres Array bedeutet vorerst keine Daten)
const isLoading = ref(true) // Ladezustand
// Datenladen simulieren: Daten nach 2 Sekunden eintragen
setTimeout(() => {
  articles.value = [
{ id: 1, title: 'Erste Schritte mit Vue3', summary: '...' },
{ id: 2, title: 'React-Vergleich', summary: '...' }
  ]
  isLoading.value = false
}, 2000)
</script>

<template>
  <div>
    <!-- Wird geladen -->
    <p v-if="isLoading">Wird geladen, bitte warten...</p>

    <!-- Liste anzeigen, wenn Daten vorhanden sind -->
    <div v-else-if="articles.length > 0">
      <div v-for="article in articles" :key="article.id" class="card">
        <h3>{{ article.title }}</h3>
        <p>{{ article.summary }}</p>
      </div>
    </div>

    <!-- Leerzustand anzeigen, wenn keine Daten vorhanden sind -->
    <p v-else>Noch keine Artikel, bitte bleiben Sie dran.</p>
  </div>
</template>

Dieses Muster deckt die drei häufigsten UI-Zustände ab:Laden → Daten vorhanden → Keine Daten。

v-if vs. v-show

DirektiveUmschaltmethodeAnfängliche RenderkostenUmschaltkostenAnwendungsfälle
v-ifFügt DOM-Knoten hinzu/entfernt sieGering (rendert nicht)Hoch (baut DOM neu auf)Szenarien, in denen sich die Bedingung selten ändert, wie z. B. Berechtigungssteuerung
v-showSchaltet die CSS-Eigenschaft display umHoch (rendert immer)Gering (ändert nur Stile)Szenarien mit häufiger Umschaltung, wie z. B. beim Tab-Wechsel

Leicht zu merken: v-show für häufiges Umschalten verwenden, v-if für stabile Bedingungen.


Hands-on: Vollständige Blog-Startseite

Kombiniere die zuvor gelernte Template-Syntax und schreibe eine vollständige Blog-Startseiten-Komponente.

Beispiel

<script setup>
import { ref } from 'vue'

// Artikel-Daten (derzeit hartkodiert; in späteren Kapiteln werden sie so geändert, dass sie per fetch geladen werden)
const articles = ref([
  {
    id: 1,
title: 'Vollständiger Leitfaden für den Einstieg in Vue3',
summary: 'Lerne die Vue3 Composition API von Grund auf und behandle Kernkonzepte wie ref, reactive, computed.',
    date: '2024-05-10',
    category: 'Vue',
    cover: '/images/vue.png'
  },
  {
    id: 2,
title: 'Asynchrone Programmierung in JavaScript erklärt',
summary: 'Verstehe Promise, async/await, Event-Loop und Microtask-Queue in einem Artikel.',
    date: '2024-05-08',
    category: 'JavaScript',
    cover: '/images/js.png'
  },
  {
    id: 3,
title: 'CSS Grid Layout in der Praxis',
summary: 'Komplexe responsive Layouts einfach mit CSS Grid umsetzen.',
    date: '2024-05-05',
    category: 'CSS',
    cover: '/images/css.png'
  }
])
</script>

<template>
  <div class="home">
    <h2 class="section-title">Neueste Artikel</h2>

    <!-- Wird geladen -->
    <p v-if="!articles.length" class="empty-tip">Noch keine Artikel vorhanden, bitte schauen Sie bald wieder vorbei.</p>

    <!-- Liste der Artikelkarten -->
    <div v-else class="article-grid">
      <div
       v-for="article in articles"
       :key="article.id"
       class="article-card"
     >
        <img :src="article.cover" :alt="article.title" class="card-cover">
        <div class="card-content">
          <span class="card-category">{{ article.category }}</span>
          <h3 class="card-title">{{ article.title }}</h3>
          <p class="card-summary">{{ article.summary }}</p>
          <span class="card-date">{{ article.date }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.home {
  max-width: 960px;
  margin: 0 auto;
  padding: 20px;
}

.section-title {
  font-size: 24px;
  margin-bottom: 20px;
  color: #333;
}

.article-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}

.article-card {
  background: #fff;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0,0,0,0.08);
  transition: transform 0.2s, box-shadow 0.2s;
  cursor: pointer;
}

.article-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}

.card-cover {
  width: 100%;
  height: 180px;
  object-fit: cover;
}

.card-content {
  padding: 16px;
}

.card-category {
  display: inline-block;
  padding: 2px 10px;
  background: #E8EEF5;
  color: #427DB8;
  border-radius: 12px;
  font-size: 12px;
  margin-bottom: 8px;
}

.card-title {
  font-size: 18px;
  margin-bottom: 8px;
  color: #222;
}

.card-summary {
  font-size: 14px;
  color: #666;
  line-height: 1.6;
  margin-bottom: 12px;
}

.card-date {
  font-size: 12px;
  color: #999;
}

.empty-tip {
  text-align: center;
  color: #999;
  padding: 60px 0;
  font-size: 16px;
}
</style>

Kapitelzusammenfassung

In diesem Kapitel haben Sie vier zentrale Funktionen der Template-Syntax kennengelernt:{{ }}Interpolation zur Anzeige von Daten,v-bind(Kurzschreibweise:) zum Binden von Attributen,v-forSchleifen zum Rendern von Listen,v-if/v-elseBedingungen zur Steuerung der Sichtbarkeit.

Zu diesem Zeitpunkt kann die Blog-Startseite bereits Artikelkarten dynamisch auf Basis von JS-Daten rendern.

Andere Erweiterungen