Begriff
MVVM (Model View ViewModel)
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
Eine Weiterentwicklung von MVC, speziell für moderne UIs (WPF, Vue, Angular). Problem bei MVC: Der Controller muss ständig Daten manuell hin- und herschaufeln. ("Nimm Text aus Inputfeld -> speicher in Model. Nimm Daten aus Model -> schreib in Label"). Lösung: Data Binding.
- Model: Die Daten (wie immer).
- View: Die UI (
<input v-model="name">). - ViewModel: Ein spezielles Objekt dazwischen.
Magie: Wenn du im ViewModel
name = "Max"setzt, ändert sich das Inputfeld automatisch. Wenn du im Inputfeld tippst, ändert sich die Variablenameautomatisch. Kein manuelles "DOM Update" mehr nötig.
Merksatz: Ein Architekturmuster, das Zwei-Wege-Datenbindung (Two-Way Binding) zwischen View und ViewModel nutzt, um die Synchronisation von Benutzeroberfläche und Datenlogik zu automatisieren.
Vue.js ist das klassische MVVM Beispiel:
// ViewModel
data() {
return { message: "Hallo" }
}
HTML (View):
<input v-model="message">
<p>{{ message }}</p>
Tippst du im Input, ändert sich das <p> sofort live mit. Ohne eine Zeile Code "onChange -> update innerHTML".
1. Two-Way vs. One-Way Binding
- Two-Way (MVVM/Angular/Vue): UI ändert Daten, Daten ändern UI. Bequem, aber manchmal chaotisch (Wer hat die Daten geändert? War es der User oder ein API-Call?).
- One-Way (React): Daten fließen nur runter (Parent -> Child). Wenn du tippen willst, musst du ein Event hochfeuern. Strikt, besser debugbar ("Unidirectional Data Flow"), aber mehr Schreibarbeit. React ist kein klassisches MVVM.
2. Observer Pattern
Wie funktioniert die Magie?
Das ViewModel macht aus deinen Variablen Observables (Getter/Setter).
Wenn du variable = 5 setzt, feuert intern ein "NotifyChanged"-Event.
Die View hat diesen Event abonniert und malt sich neu.
3. Testbarkeit
Riesenvorteil: Du kannst das ViewModel testen ohne Browser.
vm.username = "Max"; vm.login(); assert(vm.isLoggedIn).
Da das ViewModel keine UI-Referenzen (kein document.getElementById) enthält, laufen Tests rasend schnell in Node.js.
Die Reactivity Engine (Proxies vs. Getters)
Wie genau merkt das ViewModel, dass eine Variable mutiert wurde?
In älteren Frameworks wie Vue 2 oder AngularJS (Digest Cycle) basierte das "Binding" auf schmerzvollen Dirty-Checks oder manipulierten Object.defineProperty Gettern/Settern. Arrays waren extrem anfällig (vm.arr[0] = 1 triggerte kein Update).
Modernes MVVM (Vue 3, MobX) nutzt ES6 Javascript Proxies. Ein Proxy legt sich transparent um das Daten-Objekt. Wenn du vm.user.name = "Alice" schreibst, fängt der "Trap" (der Proxy-Abfangmechanismus) die Zuweisung ab, aktualisiert den Speicher und puzt zeitgleich über eine Pub/Sub-Queue das Signal an die View: "Re-Render Node id_55!". Es ist makellos und performant.
MVVM vs. Virtual DOM
Data-Binding ist nur die halbe Wahrheit. Wenn sich im ViewModel counter auf 5 ändert, könnte die View den gesamten HTML-Dokumentenbaum neu malen (was Milliarden CPU-Zyklen verbrennt).
Hier verschmilzt MVVM mit dem Virtual DOM (VDOM).
Wenn das Reactive-Signal triggert, baut die Engine den HTML-Baum rein im schnellen Arbeitsspeicher (RAM) abstrakt neu.
Dann nutzt sie einen Diffing-Algorithmus (Heuristik), der das alte VDOM mit dem neuen abstimmt. Sie stellt fest: "Ah, einzig der Text-Node im Span-Tag <span id='count'> hat sich geändert". Nur für diesen winzigen Pfad wird ein echter document.nodeValue Patch an das physikalische Browser-DOM gesendet. Das verhindert Screen-Flickering.
Globales State Management (Pinia / Vuex)
Das Problem an reinem MVVM: Wenn ViewModel A (Navbar) und ViewModel B (Profil-Seite) dieselben Daten (z.B. User-Level) brauchen, entsteht "Prop-Drilling" (Daten werden umständlich durch HTML-Tags gereicht). Enterprise-Frontend bricht aus dem strikten lokalen MVVM aus und schaltet Globale Stores (wie Redux, Pinia, NgRx) dazwischen. Der Store fungiert als eine Art Meta-ViewModel für die gesamte App ("Single Source of Truth"). Lokale Komponenten abonnieren den globalen Store und leiten Mutations-Instruktionen per "Actions" oder "Dispatches" an diesen zentralen Tresor weiter, wodurch Time-Travel-Debugging und deterministische Snapshots möglich werden.
Quick-Check
Woher kommt es?
Erfunden von Microsoft für WPF/Silverlight (C#). Populär gemacht im Web durch Knockout.js und später Vue/Angular.Controller vs ViewModel?
Controller ist ein Dirigent (sagt was passieren soll). ViewModel ist ein Zustands-Container für die View (hält die Daten bereit und reagiert automatisch).Binder?
Die unsichtbare Engine im Framework, die die Verbindung hält. In nativem JS müsste man das mühsam selbst schreiben (ProxyAPI).