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?
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.
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.
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})