226 votes

Vuex Action vs Mutations

Dans Vuex, quelle est la logique d'avoir à la fois des "actions" et des "mutations" ?

Je comprends la logique qui veut que les composants ne puissent pas modifier l'état (ce qui semble intelligent), mais le fait d'avoir à la fois des actions et des mutations donne l'impression que vous écrivez une fonction pour déclencher une autre fonction, pour ensuite modifier l'état.

Quelle est la différence entre les "actions" et les "mutations", comment fonctionnent-elles ensemble, et surtout, je suis curieux de savoir pourquoi les développeurs de Vuex ont décidé de procéder de cette façon ?

2 votes

Voir "On To Actions", je crois : vuex.vuejs.org/fr/mutations.html#sur-les-actions

0 votes

Discussion connexe : github.com/vuejs/vuex/issues/587

1 votes

Vous ne pouvez pas modifier directement l'état du magasin. Le seul moyen de modifier l'état d'un magasin est de procéder à des mutations de manière explicite. Pour cela, nous avons besoin d'actions pour engager des mutations.

273voto

Kaicui Points 46

Question 1 : Pourquoi les développeurs de Vuejs ont-ils décidé de procéder de cette manière ?

Réponse :

  1. Lorsque votre application devient grande, et que plusieurs développeurs travaillent sur ce projet, vous constaterez que la "gestion de l'état" (en particulier l'"état global"), deviendra de plus en plus compliquée.
  2. La méthode Vuex (tout comme Redux dans react.js ) offre un nouveau mécanisme de gestion de l'état, de conservation de l'état, et de "sauvegarde et suivi" (ce qui signifie que chaque action qui modifie l'état peut être suivie par outil de débogage:vue-devtools )

Question 2 : Quelle est la différence entre "action" et "mutation" ?

Voyons d'abord l'explication officielle :

Des mutations :

Les mutations Vuex sont essentiellement des événements : chaque mutation a un nom et un gestionnaire.

import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    INCREMENT (state) {
      // mutate state
      state.count++
    }
  }
})

Les actions : Les actions sont simplement des fonctions qui envoient des mutations.

// the simplest action
function increment (store) {
  store.dispatch('INCREMENT')
}

// a action with additional arguments
// with ES2015 argument destructuring
function incrementBy ({ dispatch }, amount) {
  dispatch('INCREMENT', amount)
}

Voici mon explication de ce qui précède :

  • mutation es el seul moyen pour modifier l'état
  • mutation ne se soucie pas de la logique de l'entreprise, il se soucie juste de "l'état".
  • action est une logique d'entreprise
  • action peut commettre plus d'une mutation à la fois, il ne fait qu'implémenter la logique métier, il ne se préoccupe pas des changements de données (qui sont gérés par mutation)

103 votes

Le fait qu'une action "soit la logique métier" et qu'elle puisse envoyer plusieurs mutations à la fois est utile. C'est la réponse que je cherchais. Merci.

0 votes

Il y a plus que cela... les mutations ne devraient fondamentalement QUE changer l'état comme leur effet, et rien de plus que cela ; les actions peuvent effectuer non seulement plusieurs envois de mutations, mais aussi d'autres effets secondaires. Par exemple : vous devriez jamais déclencher une notification à l'intérieur d'une mutation, mais il est parfaitement possible de déclencher une notification à l'intérieur d'une action.

16 votes

Vous, les cuys, dites que vous "expédiez une mutation". La formulation correcte n'est-elle pas que vous ENGAGEZ une mutation ?

78voto

Bas Points 399

Les mutations sont synchrones, tandis que les actions peuvent être asynchrones.

Pour le dire autrement : vous n'avez pas besoin d'actions si vos opérations sont synchrones, sinon mettez-les en œuvre.

2 votes

Cela répond en fait à une question que j'allais poser, sur le fait que l'exemple de todomvc n'utilise pas les actions.

14 votes

Vous n'avez pas besoin d'actions si vos opérations sont synchrones. : Ce n'est pas vrai : vous hacer ont besoin d'actions si vous voulez composer plusieurs mutations à partir du même module, car vous ne pouvez pas appeler une autre action à partir d'une action.

1 votes

La suite logique de cette réponse serait "alors pourquoi ne pas simplement avoir des actions et se débarrasser des mutations".

16voto

Noah Namey Points 111

Je pense que la réponse TLDR est que les mutations sont destinées à être synchrones/transactionnelles. Donc, si vous devez exécuter un appel Ajax ou tout autre code asynchrone, vous devez le faire dans une action, puis valider une mutation après, pour définir le nouvel état.

2 votes

Cela ressemble à un résumé de la documentation, ce qui n'a rien de mal. Cependant, le problème de cette réponse est que ce qu'elle affirme n'est pas nécessairement vrai. Vous POUVEZ modifier l'état à l'intérieur d'une mutation en invoquant une fonction asynchrone/AJAX, qui peut ensuite être modifié dans le callback complet. Je pense que c'est ce qui cause tant de confusion sur la raison pour laquelle les actions debe être utilisé pour les meilleures pratiques de développement lorsque vous travaillez avec Vuex. Je sais que cela a certainement été une source de confusion pour moi lorsque j'ai commencé à travailler avec Vuex.

7voto

Abdullah Khan Points 5116

Selon le docs

Actions sont similaires à mutations les différences étant que :

  • Au lieu de en mutation l'État, actions commettre mutations.
  • Actions peut contenir des asynchrone opérations.

Considérez l'extrait suivant.

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++               //Mutating the state. Must be synchronous
    }
  },
  actions: {
    increment (context) {
      context.commit('increment') //Committing the mutations. Can be asynchronous.
    }
  }
})

Gestionnaires d'action( incrémenter ) reçoit un objet contextuel qui expose le même ensemble de méthodes et de propriétés sur l'instance du magasin. méthodes/properties sur l'instance de magasin, de sorte que vous pouvez appeler context.commit pour valider une mutation, ou accéder à l'état et aux getters via context.state et context.getters

1 votes

Est-il possible d'appeler la fonction 'mutation', une méthode du composant Vuejs ?

0 votes

@AlbertoAcuña J'ai la même question, parce que lorsque j'essaie de faire cela, il jette une erreur que la mutation locale est indéfinie.

5voto

ubershmekel Points 2254

Clause de non-responsabilité - Je viens juste de commencer à utiliser Vuejs et je ne fais qu'extrapoler l'intention de conception.

Le débogage par machine à remonter le temps utilise des instantanés de l'état, et montre une chronologie des actions et des mutations. En théorie, nous aurions pu avoir juste actions à côté d'un enregistrement de setters et getters d'état pour décrire de manière synchrone la mutation. Mais alors :

  • Nous aurions des entrées impures (résultats asynchrones) à l'origine des setters et getters. Cela serait difficile à suivre logiquement et différents setters et getters asynchrones pourraient interagir de manière surprenante. Cela peut encore se produire avec mutations mais nous pouvons alors dire que la transaction doit être améliorée plutôt que d'être une condition de course dans les actions. Les mutations anonymes à l'intérieur d'une action pourraient plus facilement faire resurgir ce genre de bogues car la programmation asynchrone est fragile et difficile.
  • Le journal des transactions serait difficile à lire car il n'y aurait pas de nom pour les changements d'état. Il ressemblerait beaucoup plus à du code et serait moins anglais, sans les groupements logiques des mutations.
  • Il pourrait être plus délicat et moins performant d'instrumenter l'enregistrement de toute mutation sur un objet de données, contrairement à la situation actuelle où il existe des points de différence définis de manière synchrone - avant et après l'appel de la fonction de mutation. Je ne suis pas sûr de l'importance du problème.

Comparez le journal des transactions suivant avec les mutations nommées.

Action: FetchNewsStories
Mutation: SetFetchingNewsStories
Action: FetchNewsStories [continuation]
Mutation: DoneFetchingNewsStories([...])

Avec un journal des transactions qui n'a pas de mutations nommées :

Action: FetchNewsStories
Mutation: state.isFetching = true;
Action: FetchNewsStories [continuation]
Mutation: state.isFetching = false;
Mutation: state.listOfStories = [...]

J'espère que vous pouvez extrapoler à partir de cet exemple la complexité supplémentaire potentielle de l'asynchronisme et de la mutation anonyme dans les actions.

https://vuex.vuejs.org/en/mutations.html

Imaginons maintenant que nous déboguons l'application et que nous regardons les journaux de mutation du devtool. Pour chaque mutation enregistrée, le devtool devra capturer un instantané de l'état "avant" et "après". Cependant, le callback asynchrone dans l'exemple de mutation ci-dessus rend cela impossible : le callback n'est pas encore appelé lorsque la mutation est validée, et le devtool n'a aucun moyen de savoir quand le callback sera effectivement appelé - toute mutation d'état effectuée dans le callback est essentiellement impossible à suivre !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X