Modul 2: Vue Grundlagen

Template-Syntax

Wie Vue.js Templates funktionieren — von Interpolation bis dynamischen Attributen

Einführung

Vue.js verwendet eine HTML-basierte Template-Syntax, die es dir ermöglicht, das gerenderte DOM deklarativ an die Daten deiner Komponente zu binden. Wenn du aus der Rails-Welt kommst, wirst du viele Parallelen zu ERB-Templates finden — aber mit einem entscheidenden Unterschied: Vue-Templates sind reaktiv. Änderungen an den Daten aktualisieren automatisch das DOM.

🛤️

Rails-Vergleich: ERB vs Vue Templates

In Rails schreibst du <%= @user.name %> in ERB-Templates. Vue verwendet stattdessen doppelte geschweifte Klammern: {{ user.name }}. Der große Unterschied: ERB wird einmalig auf dem Server gerendert, Vue-Templates werden reaktiv im Browser aktualisiert.

Rails ERB
<!-- Rails: Einmaliges Server-Rendering -->
<h1><%= @user.name %></h1>
<p><%= @user.email %></p>

<!-- Vue: Reaktives Client-Rendering -->
<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>

Text-Interpolation mit {{ }}

Die einfachste Form der Datenbindung ist die Text-Interpolation mit der „Mustache"-Syntax (doppelte geschweifte Klammern). Der Inhalt wird als reiner Text eingefügt und automatisch escaped — genau wie <%= %> in ERB.

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

const nachricht = ref('Hallo Vue!')
const anzahl = ref(42)
</script>

<template>
  <p>{{ nachricht }}</p>
  <p>Anzahl: {{ anzahl }}</p>
  <p>Typ: {{ typeof anzahl }}</p>
</template>
ℹ️

Automatisches Escaping

Vue escaped automatisch alle interpolierten Werte. Das bedeutet, dass HTML-Tags als Text angezeigt werden, nicht als HTML gerendert. Das schützt dich vor XSS-Angriffen — genau wie <%= %> in Rails (im Gegensatz zu <%== %>).

Raw HTML mit v-html

Manchmal möchtest du echtes HTML rendern, z.B. wenn du formatierten Text aus einer API bekommst. Dafür gibt es die v-html-Direktive.

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

const htmlInhalt = ref('<strong>Fetter Text</strong> und <em>kursiver Text</em>')
</script>

<template>
  <!-- Escaped: zeigt die HTML-Tags als Text -->
  <p>Escaped: {{ htmlInhalt }}</p>

  <!-- Raw: rendert das HTML -->
  <p>Raw: <span v-html=\"htmlInhalt\"></span></p>
</template>
⚠️

Vorsicht mit v-html!

Verwende v-html niemals mit Benutzereingaben! Es umgeht Vues Escaping und macht deine App anfällig für XSS-Angriffe. In Rails entspricht das <%== %> oder raw() — dort gilt die gleiche Warnung.

Attribute Binding mit v-bind

Mustache-Syntax funktioniert nicht innerhalb von HTML-Attributen. Stattdessen verwendest du v-bind, um Attribute dynamisch zu binden. Die Kurzschreibweise ist ein Doppelpunkt (:).

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

const bildUrl = ref('/images/vue-logo.png')
const istDeaktiviert = ref(true)
const inputId = ref('email-feld')
</script>

<template>
  <!-- Langform -->
  <img v-bind:src=\"bildUrl\" alt=\"Vue Logo\">

  <!-- Kurzform (bevorzugt) -->
  <img :src=\"bildUrl\" alt=\"Vue Logo\">

  <!-- Boolean-Attribute -->
  <button :disabled=\"istDeaktiviert\">Senden</button>

  <!-- Dynamische ID -->
  <input :id=\"inputId\" type=\"email\">
</template>
💡

Tipp: Kurzschreibweise verwenden

In der Praxis nutzt fast jeder die Kurzform :attribut statt v-bind:attribut. Du wirst sie in Dokumentation, Tutorials und Produktionscode überall sehen.

Mehrere Attribute gleichzeitig binden

Du kannst auch ein ganzes Objekt von Attributen auf einmal binden:

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

const inputAttrs = ref({
  id: 'benutzername',
  type: 'text',
  placeholder: 'Dein Name',
  class: 'form-input'
})
</script>

<template>
  <!-- Alle Attribute werden auf das Element angewendet -->
  <input v-bind=\"inputAttrs\">
</template>

JavaScript-Ausdrücke in Templates

Vue unterstützt vollständige JavaScript-Ausdrücke innerhalb von Datenbindungen — nicht nur einfache Variablen.

Ausdruecke.vue
<template>
  <!-- Mathematik -->
  <p>{{ preis * 1.19 }}</p>

  <!-- Ternärer Operator -->
  <p>{{ istAktiv ? 'Ja' : 'Nein' }}</p>

  <!-- String-Methoden -->
  <p>{{ nachricht.toUpperCase() }}</p>
  <p>{{ name.split(' ').reverse().join(' ') }}</p>

  <!-- Template-Literals -->
  <p>{{ 'Hallo, ' + vorname + '!' }}</p>

  <!-- Array-Methoden -->
  <p>{{ items.filter(i => i.aktiv).length }} aktive Einträge</p>
</template>
⚠️

Nur Ausdrücke, keine Anweisungen!

Templates unterstützen nur Ausdrücke (expressions), die einen Wert zurückgeben. Folgendes funktioniert nicht:

NichtErlaubt.vue
<!-- ❌ Das sind Anweisungen, keine Ausdrücke -->
{{ let x = 1 }}
{{ if (ok) { return 'ja' } }}

<!-- ✅ Stattdessen: Ternärer Operator -->
{{ ok ? 'ja' : 'nein' }}

Dynamische Attributnamen

Du kannst sogar den Namen eines Attributs dynamisch gestalten, indem du eckige Klammern verwendest:

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

const attributName = ref('href')
const eventName = ref('click')
</script>

<template>
  <!-- Dynamischer Attributname -->
  <a :[attributName]=\"'/about'\">Über uns</a>

  <!-- Dynamischer Eventname -->
  <button @[eventName]=\"handleEvent\">Klick mich</button>
</template>
ℹ️

Wann braucht man das?

Dynamische Attribute sind nützlich für wiederverwendbare Komponenten, die verschiedene HTML-Elemente oder Events unterstützen müssen. Im Alltag brauchst du sie selten, aber es ist gut zu wissen, dass es geht.

Interaktive Demo

Probiere die Template-Syntax selbst aus! Tippe in das Eingabefeld und beobachte, wie sich alle Darstellungen reaktiv aktualisieren:

Template-Syntax Live-Demo
Interaktiv

{{ nachricht }}

Hallo Vue! Schreibe **fett** für v-html.

{{ nachricht.toUpperCase() }}

HALLO VUE! SCHREIBE **FETT** FÜR V-HTML.

{{ nachricht.length }}

40 Zeichen

{{ nachricht.split(\'\').reverse().join(\'\') }}

.lmth-v rüf **ttef** ebierhcS !euV ollaH

v-html Beispiel

Hallo Vue! Schreibe fett für v-html.

Tipp: Schreibe **fett** um v-html zu testen

Zusammenfassung

💡

Das Wichtigste auf einen Blick

  • {{ }} — Text-Interpolation (escaped, sicher)
  • v-html — Raw HTML (Vorsicht: XSS-Gefahr!)
  • :attribut — Kurzform für v-bind:attribut
  • JavaScript-Ausdrücke sind in allen Bindungen erlaubt
  • :[dynamisch] — Dynamische Attributnamen
  • Vue-Templates sind reaktiv, ERB-Templates nicht