Heim > Artikel > Web-Frontend > [Vue] V-Modell-gebundene Objekte werden nicht in Echtzeit aktualisiert
Originallink: Erstelle einen großen Baum
In einem Projekt, an dem ich kürzlich teilgenommen habe, wurde das vue.js-Framework im Frontend verwendet . Während dieser Zeit kam es zu einem Die Funktion erfordert das dynamische Hinzufügen von Eigenschaften zu einem gebundenen Objekt. In praktischen Anwendungen tritt jedoch ein Problem auf: Nach dem Hinzufügen von Attributen zum Objekt ändert sich der Inhalt der an das Objekt gebundenen Komponente nicht. Die Komponente muss erneut aktualisiert werden, bevor ihr Inhalt auf den geänderten Inhalt geändert wird.
Zuerst dachte ich, dass das Attribut nicht erfolgreich hinzugefügt wurde, da v-model
meiner Meinung nach in beide Richtungen gebunden ist und sich nicht in einem nicht aktualisierten Zustand befinden wird. Nachdem ich die Überwachung in Devtools überprüft hatte, stellte ich fest, dass dem entsprechenden Objekt tatsächlich die angegebenen Attribute hinzugefügt wurden.
Also habe ich mir die offizielle Dokumentation angesehen und die offizielle Erklärung gefunden: Wie Vue.js Änderungen verfolgt
Wenn Sie ein normales JavaScript-Objekt als
data
-Option an eine Vue-Instanz übergeben, Vue durchläuft alle Eigenschaften dieses Objekts und verwendetObject.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.Jede Komponenteninstanz entspricht einer Watcher-Instanz, die die „berührten“ Dateneigenschaften als Abhängigkeiten während des Komponentenrenderingprozesses aufzeichnet. Später, wenn 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 Veränderungen
Aufgrund von JavaScript-Einschränkungen kann Vue keine Änderungen in Arrays und Objekten erkennen. Dennoch gibt es Möglichkeiten, diese Einschränkungen zu umgehen und sie reaktionsfähig zu halten.
Vue kann das Hinzufügen oder Entfernen von Eigentum 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 umwandeln kann. Beispiel:
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;">var vm = new Vue({<br/> data:{<br/> a:1<br/> }<br/>})<br/><br/>// `vm.a` 是响应式的<br/><br/>vm.b = 2<br/>// `vm.b` 是非响应式的<br/></code>
Vue erlaubt kein dynamisches Hinzufügen reaktiver Eigenschaften auf Stammebene zu bereits erstellten Instanzen. 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:
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;">Vue.set(vm.someObject, <span class="hljs-string" style="color: #D69D85; line-height: 26px;">'b'</span>, 2)<br/></code>
Sie können auch die vm.$set
-Instanzmethode verwenden, die auch ein Alias für die globale Vue.set
-Methode ist:
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;">this.<span class="hljs-variable" style="color: #BD63C5; line-height: 26px;">$set</span>(this.someObject,<span class="hljs-string" style="color: #D69D85; line-height: 26px;">'b'</span>,2)<br/></code>
Manchmal müssen Sie möglicherweise mehrere zuweisen Fügen Sie einer vorhandenen Objekteigenschaft neue Werte hinzu, 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, das Sie einmischen möchten.
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;">// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`<br/>this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })<br/></code>
Dies ist eine Lösung für die Objektzuweisung this.$set(object, key, value)
, die tatsächlich einen Echtzeit-Aktualisierungseffekt erzielt. Gleichzeitig können Sie für Arrays und andere Situationen die verbleibenden offiziellen Dokumente einsehen
Wie der Beamte sagte „Aufgrund von JavaScript-Einschränkungen kann Vue Änderungen in Arrays und Objekten nicht erkennen, aber warum?“ ? Was wird passieren?
借用 Segmentfault UKer 的回答:
ECMAScript中有两种属性:数据属性 和 访问器属性; 数据属性的描述符为:Configurable,Enumerable,Writable,Value; 访问器属性的描述符为:Configurable, Enumerable,set,get。
当我们使用new Vue(obj)
,其内部发生了大体如下代码的转换,即,将数据属性转换为了访问器属性
<span style="display: block; background: url(https://imgkr.cn-bj.ufileos.com/97e4eed2-a992-4976-acf0-ccb6fb34d308.png); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #1E1E1E; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #DCDCDC; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #1E1E1E; border-radius: 5px;"><span class="hljs-keyword" style="color: #569CD6; line-height: 26px;">function</span> Vue(obj){<br/> obj.data.keys().forEach((prop, index) => {<br/> Object.defineProperty(obj.data, prop, {<br/> <span class="hljs-function" style="color: #DCDCDC; line-height: 26px;"><span class="hljs-title" style="color: #DCDCDC; line-height: 26px;">set</span></span>(){<br/> //可以在此处进行事件监听<br/> },<br/> <span class="hljs-function" style="color: #DCDCDC; line-height: 26px;"><span class="hljs-title" style="color: #DCDCDC; line-height: 26px;">get</span></span>(){<br/> <br/> }<br/> })<br/> })<br/> <span class="hljs-built_in" style="color: #4EC9B0; line-height: 26px;">return</span> obj;<br/> }<br/></code>
但是当我们后面再次使用普通的赋值,仅仅是赋值了一个数据属性的,这个属性是不会具有访问器属性的事件监听功能的。
至此,v-model
绑定数据不实时更新的问题方才得到了解决。
Das obige ist der detaillierte Inhalt von[Vue] V-Modell-gebundene Objekte werden nicht in Echtzeit aktualisiert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!