Sobes.tech
Middle

Ako funguje reaktivita v Vue.js?

sobes.tech AI

Odpoveď od AI

Reaktivita vo Vue.js je založená na vzore "pozorovateľa" (Observer).

Keď sa vytvorí inštancia Vue, prechádza všetky vlastnosti v objekte data a mení ich na getter a setter pomocou Object.defineProperty vo Vue 2 alebo Proxy vo Vue 3.

Vue 2:

  • Pri prístupe k vlastnosti (getter) Vue sleduje, ktorý komponent ju používa.
  • Pri zmene vlastnosti (setter) Vue upozorňuje všetky komponenty, ktoré ju sledovali, na potrebu aktualizácie (znovu vykresliť šablónu).

Vue 3:

  • Používa Proxy na zachytávanie všetkých operácií s objektom (pridanie, odstránenie vlastností, zmena hodnôt atď.), čím zabezpečuje úplnejšiu reaktivitu v porovnaní s Vue 2.
  • Vďaka Proxy reaktivita Vue 3 nemá obmedzenia Vue 2 (nie je potrebné $set na pridanie nových vlastností).

Kľúčové komponenty reaktivity:

  • Observer: Mení vlastnosti dát na getter a setter (Vue 2) alebo ich spracováva pomocou Proxy (Vue 3).
  • Dep (Dependency): Objekt spojený s každou reaktívnou vlastnosťou, ktorý uchováva zoznam závislých Watcherov.
  • Watcher: Predstavuje komponent, vypočítavanú vlastnosť alebo watchers, ktoré závisia od reaktívnych dát. Keď sa dáta menia, Watcher je upozornený a spúšťa príslušnú akciu (napríklad znovu vykreslenie komponentu).

Príklad (Vue 2):

// Interná implementácia (zjednodušene)
function defineReactive(obj, key, val) {
  let dep = new Dep(); // Vytvárame Dep pre vlastnosť

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      // Ak je globálny Watcher (pri vykresľovaní komponentu)
      if (Dep.target) {
        dep.depend(); // Pridávame Watcher do zoznamu závislostí Dep
      }
      return val;
    },
    set: function reactiveSetter(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify(); // Upozorňujeme všetkých závislých Watcherov
    }
  });
}

// Ako to vyzerá v komponentu
new Vue({
  data: {
    message: 'Hello' // defineReactive bude aplikované na message
  },
  template: '<div>{{ message }}</div>' // Pri prístupe k message sa pridá Watcher tohto template do Dep message
});