Vuejs e Vue.set (), aggiornano l'array


92

Sono nuovo su Vuejs. Fatto qualcosa, ma non so che sia il modo semplice / giusto.

quello che voglio

Voglio alcune date in una matrice e le aggiorno su un evento. Per prima cosa ho provato Vue.set, ma non ha funzionato. Ora, dopo aver cambiato il mio elemento dell'array:

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

Non spingo () nulla sull'array e si aggiornerà .. Ma a volte l'ultimo elemento sarà nascosto, in qualche modo ... Penso che questa soluzione sia un po 'hacky, come posso renderla stabile?

Il codice semplice è qui:

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>

Risposte:


57

VueJS non può rilevare le modifiche allo stato se si manipolano array in questo modo.

Come spiegato in Common Beginner Gotchas , dovresti usare metodi di array come push, splice o altro e non modificare mai gli indici come questo a[2] = 2né la proprietà .length di un array.

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>


1
Come detto nei documenti, $ set è solo un grazioso .splice (). Questo ha senso perché, come si dice nei documenti, dovresti modificare l'array usando i suoi metodi.
Borjante

1
Pls non combina i rientri delle tabulazioni con i rientri dello spazio, la dimensione di una tabulazione è apparentemente diversa nell'app SE, rendendo difficile leggere il tuo codice
Ferrybig

Nel mio caso l'operatore di diffusione ES6 per l'operazione push non funziona correttamente con vue
Mathias S

116

MODIFICA 2

  • Per tutte le modifiche agli oggetti che richiedono reattività, utilizzareVue.set(object, prop, value)
  • Per le mutazioni di array, puoi guardare l'elenco attualmente supportato qui

MODIFICA 1

Per vuex vorrai fare Vue.set(state.object, key, value)


Originale

Quindi solo per gli altri che arrivano a questa domanda. Sembra che a un certo punto in Vue 2. * abbiano rimosso this.items.$set(index, val)a favore di this.$set(this.items, index, val).

Splice è ancora disponibile ed ecco un collegamento ai metodi di mutazione dell'array disponibili in vue link .


Quale stringa devo fornire come "indice"?
Kokodoko

@Kokodoko puoi chiarire cosa stai cercando di fare? Se è un array, dovrebbe essere un numero per l'indice. Una stringa sarebbe se imposti un campo su un oggetto.
Martin Calvert

Ah ok, il mio IDE ha insistito sul fatto che doveva essere una stringa, deve essere un problema tecnico.
Kokodoko

Vue.set non è per vuex. E questo. $ Set è deprecato.
localhoost

2
@MartinCalvert Dice "quando si aggiunge una proprietà all'oggetto". Questo è lo scopo principale di Vue.set, non correlato solo a vuex. Deprecazione, l'ho letto sul link ma ora rileggendo, non lo capisco completamente. stackoverflow.com/questions/36671106/...
localhoost

10

Come affermato prima, VueJS semplicemente non può tenere traccia di tali operazioni (assegnazione di elementi dell'array). Tutte le operazioni tracciate da VueJS con array sono qui . Ma li copierò ancora una volta:

  • spingere()
  • pop()
  • cambio()
  • unshift ()
  • giunzione ()
  • ordinare()
  • inversione()

Durante lo sviluppo, affronti un problema: come conviverci :).

push (), pop (), shift (), unshift (), sort () e reverse () sono abbastanza semplici e ti aiutano in alcuni casi, ma l'obiettivo principale si trova all'interno di splice () , che ti consente di modificare efficacemente l'array che verrebbe monitorato da VueJs. Quindi posso condividere alcuni degli approcci, che vengono utilizzati di più lavorando con gli array.

È necessario sostituire l'elemento nell'array:

// 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)

Nota: se hai solo bisogno di modificare un campo articolo, puoi farlo semplicemente:

this.values[index].itemField = newItemFieldValue

E questo sarebbe tracciato da VueJS mentre i campi dell'oggetto (Oggetto) sarebbero tracciati.

Devi svuotare l'array:

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

In realtà puoi fare molto di più con questa funzione splice () - collegamento w3schools Puoi aggiungere più record, eliminare più record, ecc.

Vue.set () e Vue.delete ()

Vue.set () e Vue.delete () potrebbero essere utilizzati per aggiungere campi alla versione dei dati dell'interfaccia utente. Ad esempio, hai bisogno di alcuni dati o flag aggiuntivi calcolati all'interno dei tuoi oggetti. Puoi farlo per i tuoi oggetti o per l'elenco di oggetti (nel ciclo):

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

E invia i dati modificati al back-end nello stesso formato facendo ciò prima della chiamata Axios:

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

0

Un'alternativa - e un approccio più leggero al tuo problema - potrebbe essere la modifica temporanea dell'array e quindi l'assegnazione dell'intero array alla tua variabile. Poiché Vue non guarda i singoli elementi, osserverà l'intera variabile che viene aggiornata.

Quindi dovresti funzionare anche tu:

var tempArray[];

tempArray = this.items;

tempArray[targetPosition]  = value;

this.items = tempArray;

Questo dovrebbe quindi aggiornare anche il tuo DOM.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.