Dans Vuex, quelle est la logique d'avoir à la fois des «actions» et des «mutations»?
Je comprends la logique des composants ne pouvant pas modifier l'état (ce qui semble intelligent), mais avoir à la fois des actions et des mutations semble que vous écriviez une fonction pour déclencher une autre fonction, pour ensuite modifier l'état.
Quelle est la différence entre «actions» et «mutations», comment fonctionnent-elles ensemble, et plus encore, je suis curieux de savoir pourquoi les développeurs de Vuex ont décidé de le faire de cette façon?
mutations
etactions
sont définis dans la documentation de vuex comme des méthodes de changement d'état. Vous n'avez pas besoin d'une action pour commettre une mutation.Réponses:
Question 1 : Pourquoi les développeurs de Vuejs ont décidé de le faire de cette façon?
Répondre:
Question 2 : Quelle est la différence entre «action» et «mutation»?
Voyons d'abord l'explication officielle:
Voici mon explication de ce qui précède:
la source
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 implémentez-les.
la source
Je crois qu'avoir une compréhension des motivations derrière les mutations et les actions permet de mieux juger quand utiliser lesquelles et comment. Cela libère également le programmeur du fardeau de l'incertitude dans les situations où les «règles» deviennent floues. Après avoir un peu réfléchi à leurs objectifs respectifs, je suis arrivé à la conclusion que, bien qu'il puisse certainement y avoir de mauvaises façons d'utiliser les actions et les mutations, je ne pense pas qu'il y ait une approche canonique.
Essayons d'abord de comprendre pourquoi nous subissons même des mutations ou des actions.
À proprement parler, vous pouvez modifier le
state
directement depuis vos composants. Lestate
n'est qu'un objet JavaScript et il n'y a rien de magique qui annulera les modifications que vous y apportez.Cependant, en faisant cela, vous dispersez vos mutations d'état partout. Vous perdez la possibilité d'ouvrir simplement un seul module abritant l'état et de voir d'un coup d'œil quel type d'opérations peut être appliqué. Le fait d'avoir des mutations centralisées résout ce problème, mais au prix d'un passe-partout.
Je pense que si vous remplacez quelque chose de court par du passe-partout, vous voudrez que le passe-partout soit également petit. Je suppose donc que les mutations sont censées être des enveloppes très minces autour des opérations natives sur l'état, avec presque aucune logique métier. En d'autres termes, les mutations sont destinées à être principalement utilisées comme des setters.
Maintenant que vous avez centralisé vos mutations, vous avez une meilleure vue d'ensemble de vos changements d'état et puisque vos outils (vue-devtools) sont également conscients de cet emplacement, cela facilite le débogage. Il convient également de garder à l'esprit que de nombreux plugins de Vuex ne surveillent pas directement l'état pour suivre les changements, ils s'appuient plutôt sur des mutations pour cela. Les changements d'état «hors limites» leur sont donc invisibles.
Les actions, comme les mutations, résident également dans le module du magasin et peuvent recevoir l'
state
objet. Ce qui implique qu'ils pourraient également le muter directement. Alors, quel est l'intérêt d'avoir les deux? Si nous pensons que les mutations doivent rester petites et simples, cela implique que nous avons besoin d'un moyen alternatif pour héberger une logique métier plus élaborée. Les actions sont les moyens de le faire. Et comme nous l'avons établi précédemment, vue-devtools et les plugins sont conscients des changements via les mutations, pour rester cohérent, nous devons continuer à utiliser les mutations à partir de nos actions. En outre, étant donné que les actions sont censées être toutes englobantes et que la logique qu'elles encapsulent peut être asynchrone, il est logique que les actions soient également simplement rendues asynchrones dès le départ.Il est souvent souligné que les actions peuvent être asynchrones, alors que les mutations ne le sont généralement pas. Vous pouvez décider de voir la distinction comme une indication que les mutations doivent être utilisées pour tout ce qui est synchrone (et des actions pour tout ce qui est asynchrone); cependant, vous rencontriez des difficultés si, par exemple, vous deviez commettre plus d'une mutation (de manière synchrone), ou si vous deviez travailler avec un Getter à partir de vos mutations, car les fonctions de mutation ne reçoivent ni Getters ni Mutations comme arguments ...
... ce qui conduit à une question intéressante.
Je n'ai pas encore trouvé de réponse satisfaisante à cette question. J'ai vu des explications de l'équipe de base que je trouvais au mieux sans objet. Si je résume leur utilisation, les Getters sont censés être des extensions calculées (et souvent mises en cache) de l'état. En d'autres termes, ils sont fondamentalement toujours l'état, bien que cela nécessite un calcul initial et ils sont normalement en lecture seule. C'est du moins ainsi qu'ils sont encouragés à être utilisés.
Ainsi, empêcher les mutations d'accéder directement aux Getters signifie que l'une des trois choses est désormais nécessaire, si nous devons accéder à partir du premier à certaines fonctionnalités offertes par le second: (1) soit les calculs d'état fournis par le Getter sont dupliqués dans un endroit accessible. à la mutation (mauvaise odeur), ou (2) la valeur calculée (ou le Getter lui-même) est transmise comme argument explicite à la mutation (funky), ou (3) la logique du Getter elle-même est dupliquée directement dans la mutation , sans l'avantage supplémentaire de la mise en cache fournie par le Getter (puanteur).
Ce qui suit est un exemple de (2), qui dans la plupart des scénarios que j'ai rencontrés semble l'option "la moins mauvaise".
Pour moi, ce qui précède me semble non seulement un peu alambiqué, mais aussi quelque peu «fuyant», car une partie du code présent dans l'action suinte clairement de la logique interne de la mutation.
À mon avis, c'est le signe d'un compromis. Je pense que permettre à Mutations de recevoir automatiquement des Getters présente certains défis. Cela peut être soit pour la conception de Vuex lui-même, soit pour les outils (vue-devtools et al), ou pour maintenir une compatibilité descendante, ou une combinaison de toutes les possibilités énoncées.
Ce que je ne crois pas, c'est que passer vous-même Getters à vos mutations est nécessairement un signe que vous faites quelque chose de mal. Je le vois simplement comme un «correctif» de l'une des lacunes du cadre.
la source
computed
sorties. Ils sont en lecture seule. Une meilleure façon de visualiser les mutations pourrait être de supprimer lesif else
fichiers. La documentation vuex indique que vous pouvez héberger plus d'commit
un élément dans une action. Il serait donc logique de supposer que vous pourriez commettre certaines mutations en fonction de la logique. Je considère les actions comme un moyen de dicter QUELLE mutation se déclenche.Je pense que la réponse TLDR est que les mutations sont censées être synchrones / transactionnelles. Donc, si vous avez besoin d'exécuter un appel Ajax, ou de faire tout autre code asynchrone, vous devez le faire dans une action, puis valider une mutation après, pour définir le nouvel état.
la source
Les principales différences entre les actions et les mutations:
la source
Selon le
docs
Les actions sont similaires aux mutations , les différences étant que:
Considérez l'extrait suivant.
la source
Clause de non-responsabilité - Je viens juste de commencer à utiliser vuejs, il ne s'agit donc que d'extrapoler l'intention de conception.
Le débogage Time Machine 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 des setters et des getters d'État pour décrire de manière synchrone la mutation. Mais alors:mutations
transactions, mais nous pouvons alors dire que la transaction doit être améliorée au lieu d'être une condition de concurrence dans les actions. Les mutations anonymes à l'intérieur d'une action pourraient plus facilement refaire surface ces types de bogues car la programmation asynchrone est fragile et difficile.Comparez le journal de transactions suivant avec les mutations nommées.
Avec un journal de transactions sans mutations nommées:
J'espère que vous pourrez extrapoler à partir de cet exemple la complexité supplémentaire potentielle des actions asynchrones et anonymes dans les actions.
https://vuex.vuejs.org/en/mutations.html
la source
Mutations:
Actions:
Dans Redux Way
Pourquoi les deux ??
Lorsque l'application grandit, le codage et les lignes augmenteront, Cette fois-là, vous devrez gérer la logique dans Actions et non dans les mutations car les mutations sont la seule autorité pour changer l'état, cela devrait être aussi propre que possible.
la source
Cela m'a aussi dérouté, alors j'ai fait une simple démo.
component.vue
store.js
Après avoir recherché cela, la conclusion à laquelle je suis arrivé est que les mutations sont une convention centrée uniquement sur la modification des données pour mieux séparer les préoccupations et améliorer la journalisation avant et après les données mises à jour. Alors que les actions sont une couche d'abstraction qui gère la logique de niveau supérieur et appelle ensuite les mutations de manière appropriée
la source
J'utilise Vuex professionnellement depuis environ 3 ans, et voici ce que je pense avoir compris sur les différences essentielles entre les actions et les mutations, comment vous pouvez bénéficier de bien les utiliser ensemble et comment vous pouvez rendre votre vie plus difficile si vous ne l'utilisez pas bien.
L'objectif principal de Vuex est de proposer un nouveau modèle pour contrôler le comportement de votre application: la réactivité. L'idée est de décharger l'orchestration de l'état de votre application vers un objet spécialisé: un magasin. Il fournit des méthodes pratiques pour connecter vos composants directement aux données de votre magasin à utiliser à leur convenance. Cela permet à vos composants de se concentrer sur leur travail: définir un modèle, un style et un comportement de base des composants à présenter à votre utilisateur. Pendant ce temps, le magasin gère la lourde charge de données.
Ce n'est pas seulement le seul avantage de ce modèle. Le fait que les magasins soient une source unique de données pour l'intégralité de votre application offre un grand potentiel de réutilisation de ces données à travers de nombreux composants. Ce n'est pas le premier modèle qui tente de résoudre ce problème de communication inter-composants, mais là où il brille, c'est qu'il vous oblige à implémenter un comportement très sûr à votre application en interdisant fondamentalement à vos composants de modifier l'état de ces données partagées , et forcez-le plutôt à utiliser des «points de terminaison publics» pour demander des modifications.
L'idée de base est la suivante:
Cela étant dit, la magie commence lorsque nous commençons à concevoir notre application de cette manière. Par exemple:
Au final, nous avons une expérience utilisateur jugée «réactive». Du point de vue de notre utilisateur, l'élément a été supprimé immédiatement. La plupart du temps, nous nous attendons à ce que nos points de terminaison fonctionnent, c'est donc parfait. En cas d'échec, nous avons toujours un certain contrôle sur la façon dont notre application réagira , car nous avons réussi à séparer le problème de l'état de notre application frontale avec les données réelles.
Vous n'avez pas toujours besoin d'un magasin, remarquez. Si vous trouvez que vous écrivez des magasins qui ressemblent à ceci:
Il me semble que vous n'utilisez le magasin que comme magasin de données et que vous manquez peut-être l'aspect réactivité de celui-ci, en ne le laissant pas également prendre le contrôle des variables auxquelles votre application réagit. Fondamentalement, vous pouvez et devriez probablement décharger certaines lignes de code écrites dans vos composants vers vos magasins.
la source
1. à partir de la documentation :
Les actions peuvent contenir des opérations asynchrones, mais pas la mutation.
2.Nous invoquons la mutation, nous pouvons changer l'état directement. et nous pouvons également dans l'action pour changer les états comme ceci:
les Actions sont conçues pour gérer plus d'autres choses, nous pouvons y faire beaucoup de choses (nous pouvons utiliser des opérations asynchrones) puis changer d'état en y envoyant une mutation.
la source
Parce qu'il n'y a pas d'état sans mutations! Lorsqu'il est engagé - un morceau de logique, qui change l'état de manière prévisible, est exécuté. Les mutations sont le seul moyen de définir ou de modifier l'état (il n'y a donc pas de changements directs!), Et de plus - elles doivent être synchrones. Cette solution entraîne une fonctionnalité très importante: les mutations se connectent aux outils de développement. Et cela vous offre une grande lisibilité et prévisibilité!
Encore une chose - des actions. Comme on l'a dit, les actions commettent des mutations. Ils ne changent donc pas de magasin et il n'est pas nécessaire que ceux-ci soient synchrones. Mais, ils peuvent gérer un morceau supplémentaire de logique asynchrone!
la source
Il peut sembler inutile d'avoir une couche supplémentaire de
actions
juste pour appelermutations
, par exemple:Donc, si l'appel
actions
appellelogout
, pourquoi ne pas appeler la mutation elle-même?L'idée même d'une action est d'appeler plusieurs mutations à partir d'une action ou de faire une requête Ajax ou tout type de logique asynchrone que vous pouvez imaginer.
Nous pourrions éventuellement avoir des actions qui font plusieurs requêtes réseau et appellent éventuellement de nombreuses mutations différentes.
Nous essayons donc de choses que la complexité beaucoup plus de notre
Vuex.Store()
possible dans nosactions
ce qui laisse notremutations
,state
et plusgetters
propre et simple et tombe en ligne avec le genre de modularité qui rend les bibliothèques comme Vue et React populaire.la source