Heim > Web-Frontend > js-Tutorial > Hauptteil

Analyse des Vue-Datenreaktionsprinzips

php中世界最好的语言
Freigeben: 2018-05-12 11:23:14
Original
1616 Leute haben es durchsucht

Dieses Mal werde ich Ihnen eine Analyse der Prinzipien der Vue-Datenreaktionsfähigkeit und der Vorsichtsmaßnahmen für die Vue-Datenreaktionsfähigkeit bringen. Hier sind praktische Fälle, werfen wir einen Blick darauf.

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 nicht streng. Wenn (typeof obj === 'object') beispielsweise bestimmen soll, ob obj ein Objekt ist, obwohl obj kann auch Array und andere Datentypen sein, aber der Einfachheit halber wird dieser Artikel es direkt schreiben, um das Beurteilungsobjekt darzustellen, verwenden Sie 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 weiteren 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;
  }
 });
}
Nach dem Login kopieren
Zum Beispiel const obj = {} und dann die Methode defineReactive(obj,'a',2) aufrufen. Zu diesem Zeitpunkt ist innerhalb der Funktion val=2 und dann jedes Mal der Wert von obj.a wird erhalten. Sie alle erhalten den Wert von val. 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 wurde diese Funktion gefunden Es kann tatsächlich verwendet werden. 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:

Abhängigkeitssammlung

Wie geht das? Wir wissen, welches Ereignis nach der Datenänderung 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 beim Transformieren von Datenattributen eine Dep-Instanz generiert .

// 代码 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;
Nach dem Login kopieren
Code 1.2 ist Teil des Codes von Dep. Vorerst müssen Sie nur die Funktionen von zwei Methoden kennen

  1. depend() --- kann als Ereignis zum Sammeln von Abhängigkeiten verstanden werden, ohne andere Aspekte zu berücksichtigen. Die Funktion entspricht addSub()

  2. notify() --- Diese Methode ist intuitiver und führt alle abhängigen Aktualisierungen aus( ) Methoden. Später einfach die Ansicht ändern und so weiter.

Dieser Artikel befasst sich hauptsächlich mit dem Prozess der Datenantwort und geht nicht ausführlich auf die Watcher-Klasse ein. Sie müssen also nur die Funktionen der Methoden in Dep kennen.

Dann ändern Sie den Code auf 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();
  }
 });
}
Nach dem Login kopieren
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('body').innerHTML = obj.html;
}
defineReactive(obj,'html','how are you');//定义响应式的数据
Dep.target = watcher;
html();//第一次渲染界面
Dep.target = null;
Nach dem Login kopieren

此时浏览器上的界面是这样的

然后在下打开了控制台开始调试,输入:

obj.html = 'I am fine thank you'
Nach dem Login kopieren

然后就发现,按下回车的那一瞬间,奇迹发生了,页面变成了

结尾

Vue数据响应的设计模式和订阅发布模式有一点像,但是不同,每一个dep实例就是一个订阅中心,每一次发布都会把所有的订阅全部发布出去。

Vue的响应式原理其实还有很大一部分,本文主要讨论了Vue是如何让数据进行响应,但是实际上,一般的数据都是很多的,一个数据被多处使用,改变数据之后观察新值,如何观察、如何订阅、如何调度,都还有很大一部分没有讨论。主要的三个类Dep(收集依赖)、Observer(观察数据)、Watcher(订阅者,若数据有变化通知订阅者),都只提了一点点。

之前写有一篇Vue响应式----数组变异方法,针对Vue中对数组的改造进行讨论。当然之后有更多其他的文章,整个数据响应流程还有很多内容,三个主要的类都还没有讨论完。

其实阅读源码不仅仅是为了知道源码是如何工作的,更重要的是学习作者的思路与方法,我写的文章都不长,希望自己能够每次专注一个点,能够真真实实领悟到这一个点的原理。当然也想控制阅读时间,免得大家看到一半就关闭了。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

React Form组件封装步骤详解

JS跨域POST实现步骤详解

Das obige ist der detaillierte Inhalt vonAnalyse des Vue-Datenreaktionsprinzips. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage