Sobes.tech
Middle

Kaip veikia reaktivumas Vue.js?

sobes.tech AI

Atsakymas iš AI

Reaktyvumas Vue.js pagrįstas "žiūrėtojo" (Observer) modeliu.

Kai sukuriama Vue instancija, ji pereina per visas data objekto savybes ir paverčia jas getteriais ir setteriais naudodama Object.defineProperty Vue 2 arba Proxy Vue 3.

Vue 2:

  • Kai prieinama savybė (getter), Vue stebi, kuris komponentas ją naudoja.
  • Kai savybė keičiasi (setter), Vue informuoja visus komponentus, kurie ją stebėjo, kad reikia atnaujinti (perpiešti šabloną iš naujo).

Vue 3:

  • Naudoja Proxy, kad pagautų visas objektų operacijas (pridedant, ištrynus, keičiant reikšmes ir t.t.), užtikrindamas pilnesnį reaktivumą nei Vue 2.
  • Dėl Proxy, Vue 3 reaktivumas neturi Vue 2 apribojimų (nereikia $set naujoms savybėms pridėti).

Pagrindiniai reaktivumo komponentai:

  • Observer: Paverčia duomenų savybes getteriais ir setteriais (Vue 2) arba apdoroja jas naudodamas Proxy (Vue 3).
  • Dep (Dependency): Objektas, susijęs su kiekviena reaktyvia savybe, saugantis priklausomų stebėtojų (Watcher) sąrašą.
  • Watcher: Atstovauja komponentą, skaičiuojamą savybę ar stebėtoją, kurie priklauso nuo reaktyvių duomenų. Kai duomenys keičiasi, stebėtojas yra informuojamas ir paleidžia atitinkamą veiksmą (pavyzdžiui, komponento perpiešimą).

Pavyzdys (Vue 2):

// Vidinė realizacija (supaprastinta)
function defineReactive(obj, key, val) {
  let dep = new Dep(); // Sukuriame Dep savybei

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      // Jei yra globalus stebėtojas (kai piešiamas komponentas)
      if (Dep.target) {
        dep.depend(); // Pridedame stebėtoją į Dep priklausomybių sąrašą
      }
      return val;
    },
    set: function reactiveSetter(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify(); // Informuojame visus priklausomus stebėtojus
    }
  });
}

// Kaip tai atrodo komponentėje
new Vue({
  data: {
    message: 'Hello' // defineReactive bus taikomas message
  },
  template: '<div>{{ message }}</div>' // Kai prieinama message, šio šablono stebėtojas bus pridėtas prie Dep message
});