Heim  >  Artikel  >  Web-Frontend  >  Problem bei der Erkennung von Array-Änderungen in Vue

Problem bei der Erkennung von Array-Änderungen in Vue

php中世界最好的语言
php中世界最好的语言Original
2018-04-17 15:36:221604Durchsuche

Dieses Mal werde ich Ihnen das Problem der Array-Änderungserkennung in Vue vorstellen. Was sind die Vorsichtsmaßnahmen für die Array-Änderungserkennung in Vue?

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>vue</title>
 <script src="https://unpkg.com/vue@2.3.3/dist/vue.js"></script>
 <style>
  li:hover {
   cursor: pointer;
  }
 </style>
</head>
<body>
 <p class="wrap">
  <ul>
   <li v-for="item,index in items" v-on:click="handle(index)">
    <span>{{item.name}}</span>
    <span>{{numbers[index]}}</span>
   </li>
  </ul>
 </p>
 <script>
  var vm = new Vue({
   el: ".wrap",
   data: {
    numbers: [],
    items: [
     {name: 'jjj'},
     {name: 'kkk'},
     {name: 'lll'},
    ]
   },
   methods: {
    handle: function (index) {
     // WHY: 更新数据,view层未渲染,但通过console这个数组可以发现数据确实更新了
      if (typeof(this.numbers[index]) === "undefined" ) {
       this.numbers[index] = 1;
      } else {
       this.numbers[index]++;
      }
    }
   }
  });
 </script>
</body>
</html>

Der Implementierungszweck ist hier sehr klar: Ich hoffe zu erkennen, ob li existiert, wenn ich darauf klicke. Natürlich existiert es nicht, also setze ich den Wert auf 1. Wenn ich erneut darauf klicke, lasse ich die Zahl akkumulieren.

Das Problem besteht jedoch darin, dass nach dem Klicken die Nummer in der Ansichtsebene nicht aktualisiert wird und beim Konsolendruck festgestellt wird, dass die Daten tatsächlich aktualisiert sind, die Ansichtsebene sie jedoch nicht rechtzeitig erkennt. Und was ich mir überlegt habe ist: Da Vue eine bidirektionale Datenbindung implementiert, warum wird sie in der Ansichtsebene nicht aktualisiert, nachdem sich die Modellebene geändert hat? Zuerst habe ich überlegt, ob es sich hierbei um ein Array-Problem handelt, also habe ich das folgende Beispiel getestet:

Beispiel 2

Als ich zu diesem Zeitpunkt erneut testete, stellte ich fest, dass die Ansichtsebene zeitnah und effektiv aktualisiert werden kann, wenn sich die Modellebene hier ändert.
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>vue</title>
 <script src="https://unpkg.com/vue@2.3.3/dist/vue.js"></script>
 <style>
  li:hover {
   cursor: pointer;
  }
 </style>
</head>
<body>
 <p class="wrap">
  <ul>
   <li v-for="item,index in items" v-on:click="handle(index)">
    <span>{{item.name}}</span>
    <span>{{numbers[index]}}</span>
   </li>
  </ul>
 </p>
 <script>
  var vm = new Vue({
   el: ".wrap",
   data: {
    numbers: [],
    items: [
     {name: 'jjj'},
     {name: 'kkk'},
     {name: 'lll'},
    ]
   },
   methods: {
    handle: function (index) {
     // 不是数组,这里更新数据就可以直接在view层渲染
     this.items[index].name += " success";
    }
   }
  });
 </script>
</body>
</html>

Der wichtigste Satz lautet: Wenn das Objekt reagiert, stellen Sie sicher, dass das

-Attribut

nach seiner Erstellung auch reagiert und eine Ansichtsaktualisierung auslöst. Diese Methode wird hauptsächlich verwendet, um zu vermeiden, dass Vue dies nicht kann Das Attribut „Erkennen“ wurde hinzugefügt. Unter welchen Umständen kann Vue also nicht erkennen, dass Attribute hinzugefügt wurden? Laut Referenzlink haben wir im Dokument eine gute Erklärung gesehen --- Ausführliches reaktives Prinzip

Zuerst müssen wir verstehen, wie Vue die bidirektionale Datenbindung implementiert!

Übergeben Sie ein normales

JavaScript

-Objekt an die Datenoption der Vue-Instanz. Vue durchläuft alle Eigenschaften dieses Objekts und verwendet es Object.defineProperty wandelt alle diese Eigenschaften in Getter/Setter um. Object.defineProperty ist nur ES5 unterstützt Funktionen, kann diese jedoch nicht unterdrücken, weshalb Vue IE8 und niedrigere Browser nicht unterstützt. Wissensergänzung:

Accessor-Eigenschaften enthalten keine Datenwerte; sie enthalten ein Paar Getter- und Setter-Funktionen (diese beiden Funktionen sind nicht erforderlich). Wenn die Accessor-Eigenschaft gelesen wird, wird die Getter-Funktion aufgerufen, die für die Rückgabe eines gültigen Werts verantwortlich ist. Wenn die Accessor-Eigenschaft geschrieben wird, wird die Setter-Funktion aufgerufen und der neue Wert übergeben. Diese Funktion ist dafür verantwortlich, zu entscheiden, wie die Daten verarbeiten.

Accessor-Eigenschaften können nicht direkt definiert werden und müssen mit Object.defineProperty() definiert werden.

Hier ist ein Beispiel:

Dieses Beispiel soll ein gutes Verständnis der Accessor-Eigenschaften vermitteln.
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>vue</title>
</head>
<body>
 <script>
  var book={
    _year:2004,
    edition:1
  };
  Object.defineProperty(book,"year",{
    get:function(){
      return this._year;
    },
    set:function(newValue){
      if(newValue>2004){
        this._year=newValue;
        this.edition+=newValue-2004;
      }
    }
  });
  console.log(book.year); // 2004 在读取访问器属性时会调用get函数
  book.year=2005; // 在给访问器属性赋值时会调用set函数
  console.log(book.edition); // 2
 </script>
</body>
</html>

Wenn sich daher der Zugriffsattributwert unter dem Objekt ändert (Vue konvertiert die Attribute wie zuvor erwähnt in Zugriffsattribute), wird die Set-Funktion aufgerufen, und Vue kann die Änderungen über diese Set-Funktion verfolgen und verwandte Funktionen aufrufen um die Ansicht zu aktualisieren.

Jede Komponenteninstanz verfügt über ein entsprechendes Watcher-Instanzobjekt, das die Eigenschaften während des Komponenten-Rendering-Prozesses als Abhängigkeiten aufzeichnet. Wenn der Setter der Abhängigkeit später aufgerufen wird, wird der Watcher zur Neuberechnung aufgefordert, wodurch die zugehörigen Komponenten aktualisiert werden. Das heißt, während des Rendervorgangs wird die Getter-Funktion des Objektattributs aufgerufen, und dann benachrichtigt die Getter-Funktion das Wasserobjekt, um es als Abhängigkeit zu deklarieren. Wenn sich das Objektattribut nach der Abhängigkeit ändert, wird die Setter-Funktion dies tun wird aufgerufen, um den Beobachter zu benachrichtigen, und der Beobachter rendert die Komponente erneut, um die Aktualisierung abzuschließen.

OK! Da wir nun das Prinzip kennen, können wir besser verstehen, warum das vorherige Array-Problem aufgetreten ist!

Probleme bei der Änderungserkennung

Aufgrund der Einschränkungen moderner JavaScript-Browser handelt es sich tatsächlich hauptsächlich um Object.observe() Die Methodenunterstützung ist nicht gut und Vue kann das Hinzufügen oder Löschen von Objekten nicht erkennen. Allerdings führt Vue beim Initialisieren der Instanz den Setter/Getter-Konvertierungsprozess für die Eigenschaft durch, sodass die Eigenschaft von Anfang an für das Objekt vorhanden sein muss, damit Vue sie konvertieren kann.

所以对于前面的例子就不能理解了 --- 数组中index都可以看做是属性,当我们添加属性并赋值时,Vue并不能检测到对象中属性的添加或者删除,但是其的确是添加或删除了,故我们可以通过console看到变化,所以就没有办法做到响应式; 而在第二个例子中,我们是在已有的属性的基础上进行修改的,这些属性是在最开始就被Vue初始化实例时执行了setter/getter的转化过程,所以说他们的修改是有效的,model的数据可以实时的在view层中得到相应。

补充知识: 什么是 Object.observe() ?

在介绍之前,不得不残忍的说,尽管这个方法可以在某些浏览器上运行,但事实是这个方法已经废弃!

概述: 此方法用于异步地监视一个对象的修改。当对象的属性被修改时,方法的回调函数会提供一个有序的修改流,然而这个接口已经从各大浏览器移除,可以使用通用的proxy 对象。      

方法:

Object.observe(obj, callback[, acceptList])

其中obj就是被监控的对象, callback是一个回调函数,其中的参数包括changes和acceptList,

changes一个数组,其中包含的每一个对象代表一个修改行为。每个修改行为的对象包含:

  • name: 被修改的属性名称。

  • object: 修改后该对象的值。

  • type: 表示对该对象做了何种类型的修改,可能的值为"add", "update", or "delete"。

  • oldValue: 对象修改前的值。该值只在"update"与"delete"有效。

acceptList在给定对象上给定回调中要监视的变化类型列表。如果省略, ["add", "update", "delete", "reconfigure", "setPrototype", "preventExtensions"] 将会被使用。

var obj = {
 foo: 0,
 bar: 1
};
Object.observe(obj, function(changes) {
 console.log(changes);
});
obj.baz = 2;
// [{name: 'baz', object: <obj>, type: 'add'}]
obj.foo = 'hello';
// [{name: 'foo', object: <obj>, type: 'update', oldValue: 0}]
delete obj.baz;
// [{name: 'baz', object: <obj>, type: 'delete', oldValue: 2}]

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

推荐阅读:

layer前端组件图片显示功能

web前端必看4本开发书籍

Das obige ist der detaillierte Inhalt vonProblem bei der Erkennung von Array-Änderungen in Vue. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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