Heim > Artikel > Web-Frontend > So verwenden Sie Vues Observer
Dieses Mal erkläre ich Ihnen, wie Sie Vue's Observer verwenden. Was sind die Vorsichtsmaßnahmen bei der Verwendung von Vue's Observer?
Einführung:
Dieser Artikel ist eine ausführliche Rezension der offiziellen Dokumentation von Vue zu Responsive-Prinzipien (https://cn.vuejs. org/v2/guide /reactivity.html) und stellen Sie den Implementierungsprozess über den Quellcode wieder her.
Das Reaktionsprinzip kann in zwei Schritte unterteilt werden: den Prozess der Sammlung und den Prozess des Auslösens und erneuten Renderns. Es gibt drei sehr wichtige Klassen im Abhängigkeitserfassungsprozess: Watcher, Dep und Observer. In diesem Artikel wird hauptsächlich Observer erläutert.
Dieser Artikel erklärt den Inhalt von Observer, der im vorherigen Artikel nicht behandelt wurde. Schauen wir uns zuerst dieses Bild von der offiziellen Website an:
Das Wichtigste Funktion des Beobachters Es realisiert den Prozess von touch -Data(getter) - Collect als Abhängigkeit im Bild oben, bei dem es sich um den Prozess der Abhängigkeitssammlung handelt.
Nehmen wir zur Klärung den folgenden Code als Beispiel:
(Hinweis: Wischen Sie nach links und rechts, um den vollständigen Code anzuzeigen, dasselbe unten)
varvm = newVue({ el: '#demo', data: { firstName: 'Hello', fullName: '' }, watch: { firstName(val) { this.fullName = val + 'TalkingData'; }, } })
Im Quellcode stellen Sie den Prozess der Instanziierung von Vue wieder her, Schritt für Schritt von Anfang an bis zum Quellcode der Observer-Klasse (viele Codes, die in diesem Artikel nicht behandelt werden, werden weggelassen):
// src/core/instance/index.js functionVue(options) { if(process.env.NODE_ENV !== 'production'&& !(thisinstanceofVue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) } // src/core/instance/init.js Vue.prototype._init = function(options?: Object) { constvm: Component = this // ... initState(vm) // ... } // src/core/instance/state.js exportfunctioninitState(vm: Component) { // ... constopts = vm.$options if(opts.data) { initData(vm) } // ... } functioninitData(vm: Component) { letdata = vm.$options.data data = vm._data = typeofdata === 'function' ? getData(data, vm) : data || {} // ... // observe data observe(data, true/* asRootData */) }
In der initData-Methode werden die Daten verarbeitet. Durch „Beobachten“ der Daten im Element werden alle Daten beobachtbar. Schauen Sie sich als Nächstes den Code der Beobachtungsmethode an:
// src/core/observer/index.js functionobserve(value: any, asRootData: ?boolean): Observer| void{ // 如果不是对象,直接返回 if(!isObject(value) || value instanceofVNode) { return } letob: Observer | void if(hasOwn(value, 'ob') && value.ob instanceofObserver) { // 如果有实例则返回实例 ob = value.ob } elseif( // 确保value是单纯的对象,而不是函数或者是Regexp等情况 observerState.shouldConvert && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { // 实例化一个 Observer ob = newObserver(value) } if(asRootData && ob) { ob.vmCount++ } returnob }
Die Funktion der Beobachtungsmethode besteht darin, eine Observer-Instanz für Daten zu erstellen und diese zurückzugeben. Wenn Daten das Attribut ob haben, bedeutet dies, dass dies der Fall ist bereits eine Observer-Instanz, dann wird die vorhandene zurückgegeben. Beispiel. Die Antwortdaten von Vue verfügen über ein ob-Attribut, das die Observer-Instanz dieses Attributs speichert, um eine wiederholte Bindung zu verhindern. Schauen wir uns an, was während des neuen Observer(value)-Prozesses passiert:
exportclassObserver{ value: any; dep: Dep; vmCount: number; // number of vms that has this object as root $data constructor(value: any) { this.value = value this.dep = newDep() this.vmCount = 0 def(value, 'ob', this) if(Array.isArray(value)) { // ... this.observeArray(value) } else{ this.walk(value) } } walk (obj: Object) { constkeys = Object.keys(obj) for(leti = 0; i < keys.length; i++) { defineReactive(obj, keys[i], obj[keys[i]]) } } observeArray (items: Array<any>) { for(leti = 0, l = items.length; i < l; i++) { observe(items[i]) } } }
Wie Sie dem Quellcode entnehmen können, werden während der Instanziierung von Observer zwei Hauptentscheidungen getroffen. Wenn es sich um ein Array handelt, rufen Sie die oberser-Methode für jedes zu beobachtende Element im Array erneut auf. Wenn es sich um ein Nicht-Array-Objekt handelt, durchläuft jedes Attribut des Objekts und ruft die Methode defineReactive darauf auf. Die Methode defineReactive ist hier der Kern! Die Sammlung von Abhängigkeiten wird vervollständigt, indem die Methode Object.defineProperty verwendet wird, um get/set zu jeder Eigenschaft hinzuzufügen, die beobachtet werden muss. Nachdem die Abhängigkeiten erfasst wurden, verfügt jede Eigenschaft über eine Dep zum Speichern aller Watcher-Objekte. Gemäß dem Beispiel am Anfang des Artikels wird get/set zu firstName bzw. fullName hinzugefügt, und jeder von ihnen verfügt über eine Dep-Instanz, um alle Watcher-Objekte zu speichern, die sie beobachten. Das Folgende ist der Quellcode von defineReactive:
exportfunctiondefineReactive( obj: Object, key: string, val: any, customSetter?: ?Function, shallow?: boolean ) { constdep = newDep() // 获取属性的自身描述符 constproperty = Object.getOwnPropertyDeor(obj, key) if(property && property.configurable === false) { return } // cater for pre-defined getter/setters // 检查属性之前是否设置了 getter/setter // 如果设置了,则在之后的 get/set 方法中执行设置了的 getter/setter constgetter = property && property.get constsetter = property && property.set // 通过对属性再次调用 observe 方法来判断是否有子对象 // 如果有子对象,对子对象也进行依赖搜集 letchildOb = !shallow && observe(val) Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: functionreactiveGetter() { // 如果属性原本拥有getter方法则执行 constvalue = getter ? getter.call(obj) : val if(Dep.target) { // 进行依赖收集 dep.depend() if(childOb) { // 如果有子对象,对子对象也进行依赖搜集 childOb.dep.depend() // 如果属性是数组,则对每一个项都进行依赖收集 // 如果某一项还是数组,则递归 if(Array.isArray(value)) { dependArray(value) } } } returnvalue }, set: functionreactiveSetter(newVal) { // 如果属性原本拥有getter方法则执行 // 通过getter方法获取当前值,与新值进行比较 // 如果新旧值一样则不需要执行下面的操作 constvalue = getter ? getter.call(obj) : val /* eslint-disable no-self-compare */ if(newVal === value || (newVal !== newVal && value !== value)) { return } /* eslint-enable no-self-compare */ if(process.env.NODE_ENV !== 'production'&& customSetter) { customSetter() } if(setter) { // 如果属性原本拥有setter方法则执行 setter.call(obj, newVal) } else{ // 如果原本没有setter则直接赋新值 val = newVal } // 判断新的值是否有子对象,有的话继续观察子对象 childOb = !shallow && observe(newVal) // 通知所有的观察者,更新状态 dep.notify() } }) }
Gemäß den chinesischen Kommentaren im Quellcode sollten Sie verstehen können, welche Arbeit während der Ausführung von defineReactive ausgeführt wird. Tatsächlich ist der gesamte Prozess rekursiv und fügt Getter/Setter für jede Eigenschaft hinzu. Für Getter/Setter ist es außerdem erforderlich, die Rekursion (Beurteilung von Unterobjekten) für jedes Attribut Beobachtermuster durchzuführen. Als Getter wird er zum Vervollständigen der Abhängigkeitssammlung verwendet, d. h. dep.depend() im Quellcode. Sobald ein Datenelement seine Set-Methode auslöst, wird für Setter eine Aktualisierungsnachricht veröffentlicht, die alle Beobachter der Daten darüber informiert, dass sie sich ebenfalls ändern werden. Das ist dep.notify() im Quellcode.
Ich glaube, dass Sie die Methode beherrschen, nachdem Sie den Fall in diesem Artikel gelesen haben. Weitere spannende Informationen finden Sie in anderen verwandten Artikeln auf der chinesischen PHP-Website!
Empfohlene Lektüre:
Detaillierte Erläuterung der Baumsteuerung vue.js+element-ui zum Ändern von iview-Schritten
Wie ruft die übergeordnete Vue-Komponente die untergeordnete Komponente auf?
Das obige ist der detaillierte Inhalt vonSo verwenden Sie Vues Observer. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!