Sobes.tech
Middle

Co je to architektonický vzor MVVM?

sobes.tech AI

Odpověď od AI

MVVM (Model-View-ViewModel) je architektonický vzor, ktorý štruktúruje kód tak, aby rozdelil logiku aplikácie na tri navzájom prepojené komponenty:

  • Model: Predstavuje údaje a biznis logiku. Nie je závislý od UI.
  • View: Zobrazuje údaje z ViewModel a odosiela akcie používateľa (napríklad kliknutia) do ViewModel. View je pasívna a neobsahuje logiku spracovania údajov.
  • ViewModel: Funguje ako sprostredkovateľ medzi Modelom a View. Poskytuje údaje z Modelu vo formáte vhodnom na zobrazenie a spracováva akcie používateľa, aktualizujúc Model. ViewModel často využíva mechanizmy viazania dát (data binding), aby sa automaticky aktualizovala View pri zmene údajov.

Kľúčové princípy:

  • Dvojcestné viazanie dát: Zmeny vo ViewModel sa automaticky prejavia vo View a naopak (pomocou vhodných nástrojov).
  • Testovateľnosť: ViewModel je ľahko testovateľný izolovane, pretože nie je viazaný na UI.
  • Rozdelenie zodpovedností: Jasné rozdelenie logiky prezentácie, údajov a biznis logiky zjednodušuje vývoj a údržbu.

Používa sa často v aplikáciách s deklaratívnym UI, ako sú Vue.js, React (s niektorými variáciami), Angular.

Príklad najjednoduchšej štruktúry:

// Model
class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

// ViewModel
class UserViewModel {
  constructor(user) {
    this.user = user;
    this.displayName = `${user.name} (${user.age})`;
  }

  incrementAge() {
    this.user.age++;
    this.displayName = `${this.user.name} (${this.user.age})`; // Aktualizuje displayName pre View
  }
}

// View (približne, ako by to mohlo vyzerať v deklaratívnom frameworku)
/*
<template>
  <div>
    <p>{{ userViewModel.displayName }}</p>
    <button @click="userViewModel.incrementAge()">Zvýšiť vek</button>
  </div>
</template>

<script>
import { User } from './model';
import { UserViewModel } from './viewModel';

export default {
  data() {
    return {
      userViewModel: new UserViewModel(new User('Ivan', 30))
    };
  }
}
</script>
*/