Vuejs und Vue.set (), Array aktualisieren

92

Ich bin neu bei Vuejs. Etwas gemacht, aber ich weiß nicht, dass es der einfache / richtige Weg ist.

was ich möchte

Ich möchte einige Daten in einem Array haben und sie bei einem Ereignis aktualisieren. Zuerst habe ich Vue.set ausprobiert, aber es klappt nicht. Jetzt nach dem Ändern meines Array-Elements:

this.items[index] = val;
this.items.push();

Ich drücke () nichts auf das Array und es wird aktualisiert. Aber manchmal wird das letzte Element irgendwie versteckt ... Ich denke, diese Lösung ist ein bisschen hackig, wie kann ich es stabil machen?

Einfacher Code ist hier:

new Vue({
  el: '#app',
  data: {
  	f: 'DD-MM-YYYY',
    items: [
      "10-03-2017",
      "12-03-2017"
    ]
  },
  methods: {
    
    cha: function(index, item, what, count) {
    	console.log(item + " index > " + index);
      val = moment(this.items[index], this.f).add(count, what).format(this.f);
  		this.items[index] = val;
      this.items.push();
      console.log("arr length:  " + this.items.length);
    }
  }
})
ul {
  list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<div id="app">
  <ul>
    <li v-for="(index, item) in items">
    <br><br>
      <button v-on:click="cha(index, item, 'day', -1)">
      - day</button>
      {{ item }}
      <button v-on:click="cha(index, item, 'day', 1)">
      + day</button>
    <br><br>
    </li>
  </ul>
</div>

Johan Hoeksma
quelle

Antworten:

55

VueJS kann Ihre Änderungen am Status nicht übernehmen, wenn Sie Arrays wie dieses bearbeiten.

Wie in Common Beginner Gotchas erläutert , sollten Sie Array-Methoden wie Push, Splice oder was auch immer verwenden und niemals die Indizes wie diesen a[2] = 2oder die .length-Eigenschaft eines Arrays ändern .

new Vue({
  el: '#app',
  data: {
    f: 'DD-MM-YYYY',
    items: [
      "10-03-2017",
      "12-03-2017"
    ]
  },
  methods: {

    cha: function(index, item, what, count) {
      console.log(item + " index > " + index);
      val = moment(this.items[index], this.f).add(count, what).format(this.f);

      this.items.$set(index, val)
      console.log("arr length:  " + this.items.length);
    }
  }
})
ul {
  list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<div id="app">
  <ul>
    <li v-for="(index, item) in items">
      <br><br>
      <button v-on:click="cha(index, item, 'day', -1)">
      - day</button> {{ item }}
      <button v-on:click="cha(index, item, 'day', 1)">
      + day</button>
      <br><br>
    </li>
  </ul>
</div>

Borjante
quelle
Perfekter Dank für den Link. Ich kann die Antwort in 3 Minuten akzeptieren. Ich war etwas verwirrt mit Vue.set () oder $ set. Aber ich werde diese Dokumentation lesen, danke.
Johan Hoeksma
1
Wie in den Dokumenten erwähnt, ist $ set nur eine hübsche .splice (). Dies ist sinnvoll, da Sie, wie in den Dokumenten angegeben, das Array mithilfe seiner Methoden ändern sollten.
Borjante
Bitte kombinieren Sie keine Tabulatoreinrückungen mit Leerzeicheneinrückungen. Die Größe eines Tabulators unterscheidet sich anscheinend in der SE-App, was es schwierig macht, Ihren Code zu lesen
Ferrybig
In meinem Fall funktioniert der ES6-Spread-Operator für die Push-Operation nicht genau mit vue
Mathias S
113

BEARBEITEN 2

  • Für alle Objektänderungen, die Reaktivität erfordern, verwendenVue.set(object, prop, value)
  • Informationen zu Array-Mutationen finden Sie in der aktuell unterstützten Liste hier

BEARBEITEN 1

Für vuex möchten Sie tun Vue.set(state.object, key, value)


Original

Also nur für andere, die zu dieser Frage kommen. Es erscheint irgendwann in Vue 2. * Sie haben this.items.$set(index, val)zugunsten von entfernt this.$set(this.items, index, val).

Splice ist weiterhin verfügbar und hier ist ein Link zu Array-Mutationsmethoden, die in vue link verfügbar sind .

Martin Calvert
quelle
1
Genau das, wonach ich gesucht habe, hat sich in der neuesten Version einfach geändert.
WM
Welche Zeichenfolge muss ich als 'Index' angeben?
Kokodoko
@ Kokodoko kannst du klarstellen, was du versuchst zu tun? Wenn es sich um ein Array handelt, sollte es eine Zahl für den Index sein. Eine Zeichenfolge wäre, wenn Sie ein Feld für ein Objekt festlegen.
Martin Calvert
Ah ok, meine IDE bestand darauf, dass es eine Schnur sein musste, eine Panne sein musste.
Kokodoko
2
@MartinCalvert Es heißt "beim Hinzufügen einer Eigenschaft zum Objekt". Dies ist der Hauptzweck von Vue.set, der sich nicht nur auf Vuex bezieht. Veraltet, ich habe es auf dem Link gelesen, aber jetzt wieder lesen, ich verstehe es nicht ganz. stackoverflow.com/questions/36671106/…
localhoost
7

Wie bereits erwähnt, kann VueJS diese Operationen einfach nicht verfolgen (Zuweisung von Array-Elementen). Alle Operationen, die von VueJS mit Array verfolgt werden, sind hier . Aber ich werde sie noch einmal kopieren:

  • drücken()
  • Pop()
  • Verschiebung()
  • nicht verschieben ()
  • spleißen()
  • Sortieren()
  • umkehren()

Während der Entwicklung stößt man auf ein Problem - wie man damit lebt :).

push (), pop (), shift (), unshift (), sort () und reverse () sind ziemlich einfach und helfen Ihnen in einigen Fällen, aber der Hauptfokus liegt auf splice () , wodurch Sie das Array effektiv ändern können das würde von VueJs verfolgt werden. So kann ich einige der Ansätze teilen, die am häufigsten für Arrays verwendet werden.

Sie müssen Item in Array ersetzen:

// note - findIndex might be replaced with some(), filter(), forEach() 
// or any other function/approach if you need 
// additional browser support, or you might use a polyfill
const index = this.values.findIndex(item => {
          return (replacementItem.id === item.id)
        })
this.values.splice(index, 1, replacementItem)

Hinweis: Wenn Sie nur ein Elementfeld ändern müssen, können Sie dies einfach tun, indem Sie:

this.values[index].itemField = newItemFieldValue

Und dies würde von VueJS verfolgt, wenn die Elementfelder (Objektfelder) verfolgt würden.

Sie müssen das Array leeren:

this.values.splice(0, this.values.length)

Mit dieser Funktion können Sie tatsächlich viel mehr tun. Splice () - w3schools link Sie können mehrere Datensätze hinzufügen, mehrere Datensätze löschen usw.

Vue.set () und Vue.delete ()

Vue.set () und Vue.delete () können zum Hinzufügen von Feldern zu Ihrer UI-Version von Daten verwendet werden. Beispielsweise benötigen Sie einige zusätzliche berechnete Daten oder Flags in Ihren Objekten. Sie können dies für Ihre Objekte oder eine Liste von Objekten (in der Schleife) tun:

 Vue.set(plan, 'editEnabled', true) //(or this.$set)

Senden Sie bearbeitete Daten im selben Format an das Back-End zurück, bevor Sie Axios aufrufen:

 Vue.delete(plan, 'editEnabled') //(or this.$delete)
Mykola Korol
quelle
0

Eine Alternative - und eine leichtere Herangehensweise an Ihr Problem - könnte darin bestehen, das Array nur vorübergehend zu bearbeiten und dann das gesamte Array wieder Ihrer Variablen zuzuweisen. Da Vue keine einzelnen Elemente überwacht, wird die gesamte Variable aktualisiert.

Also sollte dies auch funktionieren:

var tempArray[];

tempArray = this.items;

tempArray[targetPosition]  = value;

this.items = tempArray;

Dies sollte dann auch Ihr DOM aktualisieren.

Geole
quelle