Heim  >  Artikel  >  Web-Frontend  >  Eine kurze Diskussion über das Prinzip der Vue-Datenreaktionsfähigkeit

Eine kurze Diskussion über das Prinzip der Vue-Datenreaktionsfähigkeit

不言
不言Original
2018-05-07 14:38:171441Durchsuche

Dieser Artikel führt hauptsächlich eine kurze Diskussion über das Prinzip der Vue-Datenreaktionsfähigkeit ein. Jetzt kann ich ihn mit allen teilen, die ihn benötigen

Vorwort

Vues Datenantwort basiert hauptsächlich auf Object.defineProperty(), wie sieht also der gesamte Prozess aus? Den Weg von Vue mit unseren eigenen Ideen zu gehen bedeutet eigentlich, die Prinzipien von Vue als Endpunkt zu nehmen. Lassen Sie uns den Implementierungsprozess umkehren.

Der Code in diesem Artikel ist eine Low-Profile-Version und an vielen Stellen ist if(typeof obj === 'object') nicht streng, um festzustellen, ob obj ein Objekt ist, obwohl obj kann auch ein Array usw. sein. Andere Datentypen werden in diesem Artikel jedoch der Einfachheit halber direkt geschrieben, um das Beurteilungsobjekt darzustellen. Verwenden Sie für Arrays Array.isArray().

Daten transformieren

Versuchen wir zunächst, eine Funktion zum Transformieren von Objekten zu schreiben:

Warum sollten wir das zuerst schreiben? Was ist mit Funktionen? Da die Datentransformation der grundlegendste und wichtigste Schritt ist, hängen alle nachfolgenden Schritte von diesem Schritt ab.

// 代码 1.1
function defineReactive (obj,key,val) {
 Object.defineProperty(obj,key,{
  enumerable: true,
  configurable: true,
  get: function () {
   return val;
  },
  set: function (newVal) {
   //判断新值与旧值是否相等
   //判断的后半段是为了验证新值与旧值都为NaN的情况 NaN不等于自身
   if(newVal === val || (newVal !== newVal && value !== value)){
    return ;
   }
   val = newVal;
  }
 });
}

Zum Beispiel const obj = {} und dann die Methode defineReactive(obj,'a',2) aufrufen Funktion, val=2, dann erhalten Sie jedes Mal, wenn Sie den Wert von obj.a erhalten, den Wert von val, und wenn Sie obj.a festlegen, legen Sie auch den Wert von val fest. (Jeder Aufruf von defineReactive generiert einen Abschluss, um den Wert von val zu speichern);

Prozessdiskussion

Nach der Überprüfung habe ich Ich habe festgestellt, dass diese Funktion tatsächlich verwendet werden kann. Dann besprechen wir den Antwortprozess:

  1. Eingabedaten

  2. Daten transformieren (defineReactive() )

  3. Wenn sich Daten ändern => Ereignis auslösen

Schauen wir uns den dritten Schritt an. Wie löst eine Datenänderung nachfolgende Ereignisse aus? Denken Sie sorgfältig darüber nach. Wenn Sie die Daten ändern möchten, müssen Sie zuerst die Daten festlegen. Dann können wir einfach die Methode zu set () hinzufügen, und alles ist in Ordnung.

Dann gibt es noch eine weitere wichtige Frage:

Dependency Collection

Woher wissen wir, welches Ereignis nach den Datenänderungen ausgelöst wird? In Vue:

Daten verwenden => Ansicht; Daten werden zum Rendern der Ansicht verwendet. Daher ist es der beste Zeitpunkt, Abhängigkeiten zu sammeln, wenn Vue eine Dep-Instanz generiert, die zum Sammeln von Abhängigkeiten verwendet wird.

// 代码 1.2
class Dep {
 constructor(){
  //订阅的信息
  this.subs = [];
 }

 addSub(sub){
  this.subs.push(sub);
 }

 removeSub (sub) {
  remove(this.subs, sub);
 }

 //此方法的作用等同于 this.subs.push(Watcher);
 depend(){
  if (Dep.target) {
   Dep.target.addDep(this);
  }
 }
 //这个方法就是发布通知了 告诉你 有改变啦
 notify(){
  const subs = this.subs.slice()
  for (let i = 0, l = subs.length; i < l; i++) {
   subs[i].update();
  }
 }
}
Dep.target = null;

Code 1.2 ist Teil des Codes von Dep. Vorerst müssen Sie nur die Funktionen von 2 Methoden kennen

  1. depend() --- kann als Sammeln abhängiger Ereignisse verstanden werden. Ohne Berücksichtigung anderer Aspekte entspricht die Funktion addSub()

  2. notify(. ) --- Diese Methode ist aus Gründen der Übersichtlichkeit die update()-Methode aller Abhängigkeiten. Später einfach die Ansicht ändern und so weiter.

In diesem Artikel geht es hauptsächlich um den Prozess der Datenantwort und nicht ausführlich um die Watcher-Klasse. Sie müssen also nur die Funktionen der Methoden in Dep kennen.

Dann ändern Sie den Code 1.1

//代码 1.3
function defineReactive (obj,key,val) {
 const dep = new Dep();

 Object.defineProperty(obj,key,{
  enumerable: true,
  configurable: true,
  get: function () {
   if(Dep.target){
    //收集依赖 等同于 dep.addSub(Dep.target)
    dep.depend()
   }
   return val;
  },
  set: function (newVal) {
   if(newVal === val || (newVal !== newVal && val !== val)){
    return ;
   }
   val = newVal;
   //发布改变
   dep.notify();
  }
 });
}

Es gibt einen Zweifel in diesem Code, was ist Dep.target? Warum brauchen wir Dep.target, um Abhängigkeiten zu sammeln?

  1. Dep ist eine Klasse und Dep.target ist ein Attribut der Klasse, kein Attribut der dep-Instanz.

  2. Die Dep-Klasse ist global verfügbar, sodass auf Dep.target global zugegriffen werden kann und ihr Wert beliebig geändert werden kann.

  3. Die get-Methode ist sehr verbreitet und es ist unmöglich, dep.depend() jedes Mal aufzurufen, wenn Sie sie verwenden, um einen Datenwert abzurufen.

  4. dep.depend() ist eigentlich dep.addSub(Dep.target).

  5. Dann ist es am besten, Dep.target vor der Verwendung auf ein Objekt zu setzen und Dep.target = null zu setzen, nachdem das Abonnement abgeschlossen ist.

Verifizierung

Es ist Zeit, die Verwendbarkeit einer Welle von Codes zu überprüfen

//代码 1.4

const obj = {};//这一句是不是感觉很熟悉 就相当于初始化vue的data ---- data:{obj:{}};

//低配的不能再低配的watcher对象(源码中是一个类,我这用一个对象代替了)
const watcher = {
 addDep:function (dep) {
  dep.addSub(this);
 },
 update:function(){
  html();
 }
}
//假装这个是渲染页面的
function html () {
 document.querySelector(&#39;body&#39;).innerHTML = obj.html;
}
defineReactive(obj,&#39;html&#39;,&#39;how are you&#39;);//定义响应式的数据

Dep.target = watcher;
html();//第一次渲染界面
Dep.target = null;

Die Benutzeroberfläche im Browser sieht derzeit so aus

Öffnen Sie dann die Konsole unten, um mit dem Debuggen zu beginnen, geben Sie ein :

obj.html = &#39;I am fine thank you&#39;

Dann stellte ich fest, dass in dem Moment, als ich die Eingabetaste drückte, ein Wunder geschah und die Seite zu

Ende

Das Entwurfsmuster der Vue-Datenantwort ähnelt in gewisser Weise dem Abonnement-Veröffentlichungsmuster, ist jedoch unterschiedlich. Jede Dep-Instanz ist ein Abonnement. Center, jede Veröffentlichung veröffentlicht alle Abonnements.

Es gibt tatsächlich einen großen Teil des Reaktionsprinzips von Vue, in dem es hauptsächlich darum geht, wie Vue Daten reagieren lässt. Tatsächlich werden jedoch an vielen Stellen viele Daten verwendet. Neue Werte, wie man beobachtet, wie man sich anmeldet, wie man plant, es gibt noch viele Dinge, die noch nicht besprochen wurden. Die drei Hauptklassen Dep (Abhängigkeiten sammeln), Observer (Daten beobachten) und Watcher (Abonnenten, Abonnenten benachrichtigen, wenn sich Daten ändern) wurden nur kurz erwähnt.

Ich habe zuvor einen Artikel über Vue-Reaktionsfähigkeit – Array-Mutationsmethode geschrieben, in dem ich die Transformation von Arrays in Vue bespreche. Natürlich wird es später noch weitere Artikel geben, und der gesamte Datenantwortprozess enthält noch viel Inhalt, und die drei Hauptklassen wurden noch nicht besprochen.

Tatsächlich dient das Lesen des Quellcodes nicht nur dazu, zu wissen, wie der Quellcode funktioniert, sondern, was noch wichtiger ist, die Ideen und Methoden des Autors kennenzulernen. Die Artikel, die ich schreibe, sind nicht lang, und das hoffe ich dass ich mich jeweils auf einen Punkt konzentrieren kann und das Prinzip dieses Punktes wirklich verstehen kann. Natürlich möchte ich auch die Lesezeit kontrollieren, damit die Leute das Buch nicht schließen, nachdem sie es zur Hälfte gelesen haben.

Verwandte Empfehlungen:

Zusammenfassung der Vue-Datenübertragungsmethoden

Detaillierte Erläuterung der Implementierungsschritte für die Vue-Datenübertragung

Verwendung der Vue-Datenüberwachungsmethode watch

Das obige ist der detaillierte Inhalt vonEine kurze Diskussion über das Prinzip der Vue-Datenreaktionsfähigkeit. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn