web-dev-qa-db-fra.com

Vuex - Mettre à jour un tableau entier

J'ai une application Vue.js. Cette application utilise Vuex pour la gestion de l'état. Mon magasin ressemble à ceci:

const store = new Vuex.Store({
    state: {
        items: []
    },

    mutations: {
        MUTATE_ITEMS: (state, items) => {
            state.items = items;
        }
    },

    actions: {
        loadItems: (context, items) => {
            context.commit('MUTATE_ITEMS', items);
        }
    }
  })
;

Dans mon Vue instance, j'ai la méthode suivante:

loadItems() {

  let items = [];
  for (let I=0; I<10; I++) {
    items.Push({ id:(I+1), name: 'Item #' + (I+1) });
  }
  this.$store.dispatch('loadItems', items);
},

Lorsque je l'exécute, je remarque que la liste d'éléments de mes composants enfants n'est pas mise à jour. Je soupçonne que c'est à cause du modèle de réactivité dans Vue.js. Cependant, je ne sais pas comment mettre à jour un tableau entier. De plus, je ne sais pas si je dois utiliser Vue.set dans ma mutation de magasin, l'action de magasin ou dans la méthode d'instance Vue elle-même. Je suis légèrement confus.

Composant:

<template>
    <div>
        <h1>Items ({{ items.length }})</h1>
        <table>
            <tbody>
                <tr v-for="item in items" :key="item.id">
                    <td>{{ item.id }}</td>
                </tr>
            </tbody>
        </table>
    </div>
</template>

<script>
    import { mapState } from 'vuex';

    export default {
        computed: mapState({
            items: state => state.items
        })
    };
</script>

Comment mettre à jour un tableau entier stocké de manière centralisée dans Vuex dans une application Vue.js?

7
Some User

utilisez la fonction set de vue. Cela garantira que la réactivité de la Vue entre en jeu et met à jour les objets requis.

import Vuex from 'vuex';
const store = new Vuex.Store({
    state: {
        items: []
    },

    mutations: {
        MUTATE_ITEMS: (state, items) => {
            Vue.set(state, 'items', items);
            // or, better yet create a copy of the array
            Vue.set(state, 'items', [...items]);
        }
    },

    actions: {
        loadItems: (context, items) => {
            context.commit('MUTATE_ITEMS', items);
        }
    }
  })
;

Lorsque vous traitez des tableaux ou des objets, c'est une bonne idée d'empêcher la mutabilité, ce que je fais habituellement avec un opérateur de propagation {...myObject} ou [..myArray] cela empêchera les modifications de l'objet d'une autre source pour changer votre source, c'est donc une bonne idée de l'implémenter dans les getters aussi.


Mise à jour:

Voici un exemple de travail: https://codesandbox.io/s/54on2mpkn (codesandbox vous permet d'avoir des composants de fichier unique)

Ce que j'ai remarqué, c'est que vous n'avez pas de getters , ceux-ci aident à obtenir les données. Vous pouvez les appeler directement à l'aide de valeurs calculées ou à l'aide de mapGetters. mais ils ne sont pas obligatoires. Voici trois façons d'obtenir les données

<script>
import { mapGetters } from "vuex";
import Item from "./Item";

export default {
  name: "ItemList",
  components: {
    Item
  },
  computed: {
    ...mapGetters(["items"]), // <-- using mapGetters
    itemsGet() {    // <-- using getter, but not mapGetters
      return this.$store.getters.items;
    },
    itemsDirect() {  // <--no getter, just store listener
      return this.$store.state.items;
    }
  }
};
</script>

peu importe celui que vous avez choisi du point de vue des fonctionnalités, mais l'utilisation de getters rend le code plus maintenable.

17
Daniel

Vous devez envoyer une action comme l'une des suivantes:

// dispatch with a payload
this.$store.dispatch('loadItems', {items})

// dispatch with an object
this.$store.dispatch({type: 'loadItems',items})
4