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.