Heim > Web-Frontend > js-Tutorial > Hauptteil

So verstehen Sie das Prinzip der bidirektionalen Bindung von Vue-Daten

清浅
Freigeben: 2022-01-12 15:09:17
Original
88991 Leute haben es durchsucht

Das bidirektionale Bindungsprinzip von Vue-Daten wird durch Datenhijacking in Kombination mit dem „Herausgeber-Abonnenten“-Modell erreicht. Zuerst werden die Daten überwacht und dann wird der Abonnent benachrichtigt, wenn sich die überwachten Eigenschaften ändern Zum Aktualisieren wird bei einer Aktualisierung die entsprechende Aktualisierungsfunktion ausgeführt, um die Ansicht zu aktualisieren.

So verstehen Sie das Prinzip der bidirektionalen Bindung von Vue-Daten

Das Prinzip der bidirektionalen Datenbindung von Vue wird durch Datenhijacking in Kombination mit dem Publisher-Subscriber-Modell erreicht. Zuerst werden die Daten überwacht und dann wann Wenn sich die überwachten Eigenschaften ändern, wird dem Abonnenten mitgeteilt, ob er aktualisieren soll. Bei einer Aktualisierung wird die entsprechende Aktualisierungsfunktion ausgeführt, um die Ansicht zu aktualisieren

So verstehen Sie das Prinzip der bidirektionalen Bindung von Vue-Daten

[Empfohlener Kurs: Vue-Tutorial]

MVC-Modus

Der vorherige MVC-Modus war eine Einwegbindung, also das Modell war an die Ansicht gebunden. Wenn wir das Modell mit JavaScript-Code aktualisieren, wird die Ansicht automatisch aktualisiert

So verstehen Sie das Prinzip der bidirektionalen Bindung von Vue-Daten

MVVM-Modus

MVVM Der Modus ist Model–View–ViewModel-Modus. Es erkennt, dass Änderungen in View automatisch in ViewModel widergespiegelt werden und umgekehrt. Das Verständnis der bidirektionalen Bindung besteht darin, dass die Daten des Modells automatisch aktualisiert werden, wenn der Benutzer die Ansicht aktualisiert. Dies ist eine bidirektionale Bindung. Genauer gesagt wird auf der Grundlage der unidirektionalen Bindung ein Änderungsereignis (Eingabeereignis) dynamisch zu den Eingabeelementen Eingabe, Textare usw. hinzugefügt (das Änderungsereignis wird ausgelöst und der Status der Ansicht wird aktualisiert). das Modell modifizieren.

So verstehen Sie das Prinzip der bidirektionalen Bindung von Vue-Daten

Prinzip der bidirektionalen Bindung

Die bidirektionale Bindung von Vue-Daten erfolgt durch Datenhijacking in Kombination mit dem Publisher-Abonnenten-Modell. Implementiert

Wir wissen bereits, dass wir zur Implementierung der bidirektionalen Datenbindung zunächst die Daten kapern und überwachen müssen, also müssen wir einen Beobachter einrichten, um alle Eigenschaften zu überwachen. Wenn sich das Attribut ändert, müssen Sie dem Abonnenten-Watcher mitteilen, ob es aktualisiert werden muss. Da es viele Abonnenten gibt, benötigen wir eine Nachrichtenabonnenten-Abteilung, um diese Abonnenten gezielt zu sammeln und sie dann einheitlich zwischen dem Beobachter und dem Beobachter zu verwalten. Als nächstes müssen wir auch einen Anweisungsparser kompilieren, um jedes Knotenelement zu scannen und zu analysieren, die relevanten Anweisungen (z. B. V-Modell, V-On) in einem Abonnenten-Watcher zu initialisieren und die Vorlagendaten zu ersetzen oder sie zu binden Entsprechende Funktion, wenn die Der Abonnenten-Watcher empfängt die Änderung des entsprechenden Attributs und führt die entsprechende Aktualisierungsfunktion aus, um die Ansicht zu aktualisieren.

Als nächstes führen wir die folgenden 3 Schritte aus, um eine bidirektionale Datenbindung zu erreichen:

(1) Implementieren Sie einen Listener-Beobachter, um alle Attribute zu kapern und zu überwachen. Wenn es Änderungen gibt, benachrichtigen Sie die Abonnenten .

(2) Implementieren Sie einen Abonnenten-Watcher. Jeder Watcher ist an eine Aktualisierungsfunktion gebunden. Der Watcher kann Benachrichtigungen über Eigenschaftsänderungen empfangen und entsprechende Funktionen ausführen, um die Ansicht zu aktualisieren.

(3) Implementieren Sie eine Parser-Kompilierung, die die relevanten Anweisungen jedes Knotens (V-Modell, V-On und andere Anweisungen) scannen und analysieren kann Anweisungen: Der Parser kompiliert die Vorlagendaten dieses Knotentyps, damit sie in der Ansicht angezeigt werden können, und initialisiert dann den entsprechenden Abonnenten (Watcher).

So verstehen Sie das Prinzip der bidirektionalen Bindung von Vue-Daten

Implementieren eines Observers

Observer ist ein Daten-Listener und seine Kernimplementierungsmethode ist Object.defineProperty(). Wenn Sie alle Eigenschaften überwachen möchten, können Sie alle Eigenschaftswerte durch Rekursion durchlaufen und sie mit Object.defineProperty() verarbeiten.
Der folgende Code implementiert einen Observer.

function Observer(data) {    this.data = data;    this.walk(data);
}

Observer.prototype = {    walk: function(data) {        
var self = this;        //这里是通过对一个对象进行遍历,对这个对象的所有属性都进行监听
 Object.keys(data).forEach(function(key) {
       self.defineReactive(data, key, data[key]);
        });
    },    defineReactive: function(data, key, val) {        
    var dep = new Dep();      // 递归遍历所有子属性
        var childObj = observe(val);        
        Object.defineProperty(data, key, {            
        enumerable: true,            
        configurable: true,            
        get: function getter () {                
        if (Dep.target) {                  
        // 在这里添加一个订阅者
                  console.log(Dep.target)
                    dep.addSub(Dep.target);
                }                return val;
            },           
            // setter,如果对一个对象属性值改变,就会触发setter中的dep.notify(),
            通知watcher(订阅者)数据变更,执行对应订阅者的更新函数,来更新视图。
            set: function setter (newVal) {                
            if (newVal === val) {                    
            return;
                }
                val = newVal;              
                // 新的值是object的话,进行监听
                childObj = observe(newVal);
                dep.notify();
            }
        });
    }
};function observe(value, vm) {    if (!value || typeof value !== 'object') {        
return;
    }    return new Observer(value);
};// 消息订阅器Dep,订阅器Dep主要负责收集订阅者,然后在属性变化的时候执行对应订阅者的更新函数
function Dep () {    
this.subs = [];
}
Dep.prototype = {  /**
   * [订阅器添加订阅者]
   * @param  {[Watcher]} sub [订阅者]
   */
    addSub: function(sub) {        
    this.subs.push(sub);
    },  // 通知订阅者数据变更
    notify: function() {        
    this.subs.forEach(function(sub) {
            sub.update();
        });
    }
};
Dep.target = null;
Nach dem Login kopieren

Als ich mir in Observer den Quellcode anderer Leute ansah, verstand ich nicht, woher Dep.target kam. Ich glaube, einige Leute werden die gleichen Fragen haben wie ich. Machen Sie sich hier keine Sorgen. Wenn Sie über Watcher schreiben, werden Sie feststellen, dass dies Dep.target von Watcher stammt.

Implementieren eines Watchers

Watcher ist ein Abonnent. Wird verwendet, um die vom Observer gesendete Aktualisierungsnachricht zu verarbeiten und die an den Watcher gebundene Aktualisierungsfunktion auszuführen.

Der folgende Code implementiert einen Watcher

function Watcher(vm, exp, cb) {    
this.cb = cb;    
this.vm = vm;    
this.exp = exp;    
this.value = this.get();  // 将自己添加到订阅器的操作}

Watcher.prototype = {    update: function() {        
this.run();
    },    run: function() {        
    var value = this.vm.data[this.exp];        
    var oldVal = this.value;        
    if (value !== oldVal) {            
    this.value = value;            
    this.cb.call(this.vm, value, oldVal);
        }
    },    get: function() {
        Dep.target = this;  // 缓存自己
        var value = this.vm.data[this.exp]  // 强制执行监听器里的get函数
        Dep.target = null;  // 释放自己
        return value;
    }
};
Nach dem Login kopieren

Beim Studium des Codes ist es meiner Meinung nach am kompliziertesten, die Parameter dieser Funktionen zu verstehen. Die Funktionen Auch diese Funktionen sind leicht verständlich. vm ist das später zu schreibende SelfValue-Objekt, das einem neuen Vue-Objekt in Vue entspricht. exp ist der Attributwert des V-Modells des Knotenknotens oder v-on:click und anderer Anweisungen.

Wie Sie dem obigen Code entnehmen können, zeigt Dep.target in der Getter-Funktion von Watcher auf sich selbst, das Watcher-Objekt. In der Getter-Funktion fügt

var value = this.vm.data[this.exp]  // 强制执行监听器里的get函数。
这里获取vm.data[this.exp] 时,会调用Observer中Object.defineProperty中的get函数
get: function getter () {                
if (Dep.target) {                  
// 在这里添加一个订阅者                  
console.log(Dep.target)                    
dep.addSub(Dep.target);                
}                
return val;            
},
Nach dem Login kopieren

somit den Watcher zum Abonnenten hinzu, was das Problem löst, woher das obige Dep.target kommt.

Eine Kompilierung implementieren

Compile主要的作用是把new SelfVue 绑定的dom节点,(也就是el标签绑定的id)遍历该节点的所有子节点,找出其中所有的v-指令和" {{}} ".
(1)如果子节点含有v-指令,即是元素节点,则对这个元素添加监听事件。(如果是v-on,则node.addEventListener('click'),如果是v-model,则node.addEventListener('input'))。接着初始化模板元素,创建一个Watcher绑定这个元素节点。

(2)如果子节点是文本节点,即" {{ data }} ",则用正则表达式取出" {{ data }} "中的data,然后var initText = this.vm[exp],用initText去替代其中的data。

实现一个MVVM

可以说MVVM是Observer,Compile以及Watcher的“boss”了,他需要安排给Observer,Compile以及Watche做的事情如下

(1)Observer实现对MVVM自身model数据劫持,监听数据的属性变更,并在变动时进行notify
(2)Compile实现指令解析,初始化视图,并订阅数据变化,绑定好更新函数
(3)Watcher一方面接收Observer通过dep传递过来的数据变化,一方面通知Compile进行view update。
最后,把这个MVVM抽象出来,就是vue中Vue的构造函数了,可以构造出一个vue实例。

最后写一个html测试一下我们的功能

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>self-vue</title></head><style>
    #app {        
    text-align: center;
    }</style><body>
    <div id="app">
        <h2>{{title}}</h2>
        <input v-model="name">
        <h1>{{name}}</h1>
        <button v-on:click="clickMe">click me!</button>
    </div></body><script src="js/observer.js"></script>
    <script src="js/watcher.js"></script>
    <script src="js/compile.js"></script>
    <script src="js/mvvm.js"></script>
    <script type="text/javascript">
     var app = new SelfVue({        
     el: &#39;#app&#39;,        
     data: {            
     title: &#39;hello world&#39;,            
     name: &#39;canfoo&#39;
        },        
        methods: {            
        clickMe: function () {                
        this.title = &#39;hello world&#39;;
            }
        },        
        mounted: function () {            
        window.setTimeout(() => {                
        this.title = &#39;你好&#39;;
            }, 1000);
        }
    });</script></html>
Nach dem Login kopieren

先执行mvvm中的new SelfVue(...),在mvvm.js中,

observe(this.data);
new Compile(options.el, this);
Nach dem Login kopieren

先初始化一个监听器Observer,用于监听该对象data属性的值。
然后初始化一个解析器Compile,绑定这个节点,并解析其中的v-," {{}} "指令,(每一个指令对应一个Watcher)并初始化模板数据以及初始化相应的订阅者,并把订阅者添加到订阅器中(Dep)。这样就实现双向绑定了。
如果v-model绑定的元素,

<input v-model="name">
Nach dem Login kopieren

即输入框的值发生变化,就会触发Compile中的

node.addEventListener(&#39;input&#39;, function(e) {            
var newValue = e.target.value;            
if (val === newValue) {                
return;
            }            
            self.vm[exp] = newValue;
            val = newValue;
        });
Nach dem Login kopieren

self.vm[exp] = newValue;这个语句会触发mvvm中SelfValue的setter,以及触发Observer对该对象name属性的监听,即Observer中的Object.defineProperty()中的setter。setter中有通知订阅者的函数dep.notify,Watcher收到通知后就会执行绑定的更新函数。
最后的最后就是效果图啦:

So verstehen Sie das Prinzip der bidirektionalen Bindung von Vue-Daten

Das obige ist der detaillierte Inhalt vonSo verstehen Sie das Prinzip der bidirektionalen Bindung von Vue-Daten. 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
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!