Vuejs et Vue.set (), mettre à jour le tableau

92

Je suis nouveau sur Vuejs. J'ai fait quelque chose, mais je ne sais pas que c'est la manière simple / correcte.

ce que je veux

Je veux des dates dans un tableau et les mettre à jour sur un événement. J'ai d'abord essayé Vue.set, mais cela ne fonctionne pas. Maintenant, après avoir changé mon élément de tableau:

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

Je ne pousse () rien sur le tableau et il se mettra à jour .. Mais parfois le dernier élément sera caché, d'une manière ou d'une autre ... Je pense que cette solution est un peu hacky, comment puis-je la rendre stable?

Le code simple est ici:

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
la source

Réponses:

57

VueJS ne peut pas récupérer vos modifications d'état si vous manipulez des tableaux comme celui-ci.

Comme expliqué dans Common Beginner Gotchas , vous devez utiliser des méthodes de tableau comme push, splice ou autre et ne jamais modifier les index comme celui-ci a[2] = 2ni la propriété .length d'un tableau.

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
la source
1
Comme indiqué dans la documentation, $ set n'est qu'un joli .splice (). Cela a du sens car, comme ils le disent dans la documentation, vous devez modifier le tableau en utilisant ses méthodes.
Borjante
1
Veuillez ne pas combiner les retraits de tabulation avec les retraits d'espace, la taille d'un onglet est apparemment différente sur l'application SE, ce qui rend difficile la lecture de votre code
Ferrybig
Dans mon cas, l'opérateur de propagation ES6 pour l'opération push ne fonctionne probablement pas avec vue
Mathias S
116

MODIFIER 2

  • Pour tous les changements d'objet nécessitant une réactivitéVue.set(object, prop, value)
  • Pour les mutations de tableau, vous pouvez consulter la liste actuellement prise en charge ici

MODIFIER 1

Pour vuex, vous voudrez faire Vue.set(state.object, key, value)


Original

Donc juste pour les autres qui viennent à cette question. Il apparaît à un moment donné dans Vue 2. * ils ont supprimé this.items.$set(index, val)en faveur de this.$set(this.items, index, val).

Splice est toujours disponible et voici un lien vers les méthodes de mutation de tableau disponibles dans le lien vue .

Martin Calvert
la source
Quelle chaîne dois-je fournir comme «index»?
Kokodoko le
@Kokodoko pouvez-vous clarifier ce que vous essayez de faire? S'il s'agit d'un tableau, il doit s'agir d'un nombre pour l'index. Une chaîne serait si vous définissez un champ sur un objet.
Martin Calvert
Ah ok, mon IDE a insisté sur le fait que ça devait être une chaîne, ça devait être un pépin.
Kokodoko
Vue.set n'est pas pour vuex. Et ceci. $ Set obsolète.
localhoost
2
@MartinCalvert Il dit "lors de l'ajout d'une propriété à l'objet". C'est l'objectif principal de Vue.set, qui n'est pas uniquement lié à vuex. Dépréciation, je l'ai lu sur le lien mais en lisant à nouveau, je ne le comprends pas entièrement. stackoverflow.com/questions/36671106/…
localhoost
10

Comme indiqué précédemment - VueJS ne peut tout simplement pas suivre ces opérations (affectation d'éléments de tableau). Toutes les opérations suivies par VueJS avec array sont ici . Mais je vais les copier encore une fois:

  • pousser()
  • pop()
  • décalage()
  • décaler ()
  • épissure()
  • Trier()
  • inverser()

Pendant le développement, vous rencontrez un problème - comment vivre avec ça :).

push (), pop (), shift (), unshift (), sort () et reverse () sont assez simples et vous aident dans certains cas, mais l'objectif principal réside dans le splice () , qui vous permet de modifier efficacement le tableau qui serait suivi par VueJs. Je peux donc partager certaines des approches les plus utilisées avec les tableaux.

Vous devez remplacer l'élément dans le tableau:

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

Remarque: si vous avez juste besoin de modifier un champ d'élément, vous pouvez le faire simplement en:

this.values[index].itemField = newItemFieldValue

Et cela serait suivi par VueJS car les champs de l'élément (objet) seraient suivis.

Vous devez vider le tableau:

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

En fait, vous pouvez faire beaucoup plus avec cette fonction splice () - lien w3schools Vous pouvez ajouter plusieurs enregistrements, supprimer plusieurs enregistrements, etc.

Vue.set () et Vue.delete ()

Vue.set () et Vue.delete () peuvent être utilisés pour ajouter un champ à votre version d'interface utilisateur des données. Par exemple, vous avez besoin de données ou d'indicateurs calculés supplémentaires dans vos objets. Vous pouvez le faire pour vos objets, ou liste d'objets (dans la boucle):

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

Et renvoyez les données modifiées au back-end dans le même format avant l'appel d'Axios:

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

Une alternative - et une approche plus légère à votre problème - pourrait être, simplement éditer le tableau temporairement, puis attribuer le tableau entier à votre variable. Parce que Vue ne regarde pas les éléments individuels, il surveillera la totalité de la variable mise à jour.

Donc, cela devrait également fonctionner:

var tempArray[];

tempArray = this.items;

tempArray[targetPosition]  = value;

this.items = tempArray;

Cela devrait également mettre à jour votre DOM.

Geole
la source