Tauchen Sie tief in die Responsive-Prinzipien ein
Inhaltsverzeichnis
So verfolgen Sie Änderungen
Wenn Sie einen Normalwert festlegen Das JavaScript-Objekt wird als Option data
an die Vue-Instanz übergeben. Vue durchläuft alle Eigenschaften dieses Objekts und verwendet Object.defineProperty
, um alle diese Eigenschaften in Getter/Setter umzuwandeln. Object.defineProperty
ist eine Funktion in ES5, die nicht angepasst werden kann, weshalb Vue IE8 und niedrigere Browser nicht unterstützt.
Diese Getter/Setter sind für den Benutzer unsichtbar, aber intern ermöglichen sie Vue, Abhängigkeiten zu verfolgen und Änderungen zu benachrichtigen, wenn auf Eigenschaften zugegriffen und diese geändert werden. Hierbei ist zu beachten, dass verschiedene Browser Getter/Setter beim Drucken von Datenobjekten auf der Konsole unterschiedlich formatieren. Daher wird empfohlen, vue-devtools zu installieren, um eine benutzerfreundlichere Benutzeroberfläche zum Überprüfen von Daten zu erhalten.
Jede Komponenteninstanz entspricht einer Watcher-Instanz, die die „berührten“ Datenattribute als Abhängigkeiten während des Komponentenrenderingprozesses aufzeichnet. Wenn später der Setter der Abhängigkeit ausgelöst wird, wird der Watcher benachrichtigt, was dazu führt, dass die zugehörige Komponente erneut gerendert wird.
Hinweise zur Erkennung von Änderungen
Eingeschränkt durch modernes JavaScript (und Object.observe
Ebenfalls veraltet), Vue kann das Hinzufügen oder Löschen von Objekteigenschaften nicht erkennen. Da Vue beim Initialisieren der Instanz eine Getter/Setter-Konvertierung für die Eigenschaft durchführt, muss die Eigenschaft im data
-Objekt vorhanden sein, damit Vue sie in reaktiv konvertieren kann. Beispiel:
var vm = new Vue({ data:{ a:1 } }) // `vm.a` 是响应式的 vm.b = 2 // `vm.b` 是非响应式的
Vue erlaubt das dynamische Hinzufügen reaktiver Eigenschaften auf Stammebene zu bereits erstellten Instanzen nicht. Sie können jedoch reaktive Eigenschaften zu verschachtelten Objekten hinzufügen, indem Sie die Methode Vue.set(object, propertyName, value)
verwenden. Zum Beispiel für:
Vue.set(vm.someObject, 'b', 2)
Sie können auch die Instanzmethode vm.$set
verwenden, die auch ein Alias für die globale Methode Vue.set
ist:
this.$set(this.someObject,'b',2)
Manchmal müssen Sie einem vorhandenen Objekt möglicherweise mehrere neue Eigenschaften zuweisen, z. B. mithilfe von Object.assign()
oder _.extend()
. Neue Eigenschaften, die dem Objekt auf diese Weise hinzugefügt werden, lösen jedoch keine Aktualisierung aus. In diesem Fall sollten Sie ein neues Objekt mit den Eigenschaften des Originalobjekts und des Objekts erstellen, in das Sie verschmelzen möchten.
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })` this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
Es gibt auch einige Array-bezogene Überlegungen, die bereits in Listenrendering besprochen wurden.
Deklarieren Sie reaktive Eigenschaften
dank Vue Das dynamische Hinzufügen reaktiver Eigenschaften auf Stammebene ist nicht zulässig. Daher müssen Sie vor der Initialisierung der Instanz alle reaktiven Eigenschaften auf Stammebene deklarieren, auch wenn es sich nur um einen Nullwert handelt:
var vm = new Vue({ data: { // 声明 message 为一个空值字符串 message: '' }, template: '<div>{{ message }}</div>' }) // 之后设置 `message` vm.message = 'Hello!'
wenn Sie nicht dabei sind die data
-Option Declare message
und Vue warnt Sie, dass die Renderfunktion versucht, auf eine nicht vorhandene Eigenschaft zuzugreifen.
Diese Einschränkung hat technische Gründe. Sie eliminiert eine Art Randfall im Abhängigkeitsverfolgungssystem und ermöglicht außerdem eine bessere Zusammenarbeit von Vue-Instanzen mit dem Typprüfungssystem. Aber gleichzeitig gibt es einen wichtigen Aspekt im Hinblick auf die Wartbarkeit des Codes: data
Objekte sind wie das Schema des Komponentenzustands. Durch die vorherige Deklaration aller reaktiven Eigenschaften wird der Komponentencode leichter verständlich, wenn er in Zukunft geändert oder von anderen Entwicklern gelesen wird.
Asynchrone Update-Warteschlange
Vielleicht ist es Ihnen noch nicht aufgefallen, dass Vue aktualisiert wird Das DOM wird asynchron ausgeführt. Solange Vue auf Datenänderungen wartet, öffnet es eine Warteschlange und puffert alle Datenänderungen, die in derselben Ereignisschleife auftreten. Wenn derselbe Watcher mehrmals ausgelöst wird, wird er nur einmal in die Warteschlange verschoben. Diese Deduplizierung während der Pufferung ist wichtig, um unnötige Berechnungen und DOM-Operationen zu vermeiden. Beim nächsten „Tick“ der Ereignisschleife leert Vue dann die Warteschlange und führt die eigentliche (deduplizierte) Arbeit aus. Vue versucht intern, native Promise.then
, MutationObserver
und setImmediate
für asynchrone Warteschlangen zu verwenden. Wenn die Ausführungsumgebung dies nicht unterstützt, wird stattdessen setTimeout(fn, 0)
verwendet.
Wenn Sie beispielsweise vm.someData = 'new value'
festlegen, wird die Komponente nicht sofort neu gerendert. Wenn die Warteschlange geleert wird, wird die Komponente beim nächsten „Tick“ der Ereignisschleife aktualisiert. In den meisten Fällen müssen wir uns über diesen Vorgang keine Gedanken machen, aber wenn Sie etwas auf der Grundlage des aktualisierten DOM-Status tun möchten, kann dies etwas schwierig sein. Während Vue.js Entwickler im Allgemeinen dazu ermutigt, „datengesteuert“ zu denken und den direkten Kontakt mit dem DOM zu vermeiden, müssen wir dies manchmal tun. Um zu warten, bis Vue die Aktualisierung des DOM nach den Datenänderungen abgeschlossen hat, können Sie Vue.nextTick(callback)
unmittelbar nach den Datenänderungen verwenden. Auf diese Weise wird die Rückruffunktion aufgerufen, nachdem die DOM-Aktualisierung abgeschlossen ist. Zum Beispiel:
<div id="example">{{message}}</div>
var vm = new Vue({ el: '#example', data: { message: '123' } }) vm.message = 'new message' // 更改数据 vm.$el.textContent === 'new message' // false Vue.nextTick(function () { vm.$el.textContent === 'new message' // true })
Es ist besonders praktisch, die vm.$nextTick()
-Instanzmethode innerhalb einer Komponente zu verwenden, da sie kein globales Vue
erfordert und das this
in der Rückruffunktion automatisch an die aktuelle Vue-Instanz gebunden wird:
Vue.component('example', { template: '<span>{{ message }}</span>', data: function () { return { message: '未更新' } }, methods: { updateMessage: function () { this.message = '已更新' console.log(this.$el.textContent) // => '未更新' this.$nextTick(function () { console.log(this.$el.textContent) // => '已更新' }) } } })
Da $nextTick()
ein Promise
-Objekt zurückgibt, können Sie das neue verwenden Die ES2016 async/await-Syntax erreicht dasselbe:
methods: { updateMessage: async function () { this.message = '已更新' console.log(this.$el.textContent) // => '未更新' await this.$nextTick() console.log(this.$el.textContent) // => '已更新' } }