Em Vuex, qual é a lógica de ter "ações" e "mutações"?
Entendo a lógica dos componentes não serem capazes de modificar o estado (o que parece inteligente), mas ter ações e mutações parece que você está escrevendo uma função para acionar outra função e depois alterar o estado.
Qual é a diferença entre "ações" e "mutações", como elas funcionam juntas e, mais ainda, estou curioso por que os desenvolvedores da Vuex decidiram fazer dessa maneira?
mutations
eactions
são definted na documentação vuex como métodos de mudança de estado. Você não precisa de uma ação para cometer uma mutação.Respostas:
Pergunta 1 : Por que os desenvolvedores do Vuejs decidiram fazer dessa maneira?
Responda:
Pergunta 2 : Qual a diferença entre "ação" e "mutação"?
Vamos ver a explicação oficial primeiro:
Aqui está a minha explicação do acima:
fonte
As mutações são síncronas, enquanto as ações podem ser assíncronas.
Em outras palavras: você não precisa de ações se suas operações são síncronas; caso contrário, implemente-as.
fonte
Acredito que ter uma compreensão das motivações por trás de Mutações e ações permite julgar melhor quando usar qual e como. Também libera o programador do fardo da incerteza em situações em que as "regras" se tornam imprecisas. Depois de pensar um pouco sobre seus respectivos propósitos, cheguei à conclusão de que, embora possa haver formas erradas de usar Ações e Mutações, não acho que exista uma abordagem canônica.
Vamos primeiro tentar entender por que passamos por mutações ou ações.
A rigor, você pode alterar
state
diretamente os componentes. Ostate
é apenas um objeto JavaScript e não há nada mágico que reverta as alterações feitas nele.No entanto, ao fazer isso, você está espalhando suas mutações de estado por todo o lugar. Você perde a capacidade de simplesmente abrir um único módulo que hospeda o estado e ver rapidamente que tipo de operações pode ser aplicada a ele. A existência de mutações centralizadas resolve isso, embora ao custo de alguns clichês.
Eu acho que se você substituir algo curto pelo clichê, você desejará que o clichê também seja pequeno. Portanto, presumo que as mutações devem ser invólucros muito finos em torno das operações nativas no estado, com quase nenhuma lógica de negócios. Em outras palavras, as mutações devem ser usadas principalmente como criadores.
Agora que você centralizou suas mutações, você tem uma melhor visão geral de suas alterações de estado e, como suas ferramentas (vue-devtools) também conhecem esse local, facilita a depuração. Também é importante ter em mente que muitos plugins da Vuex não assistem diretamente ao estado para rastrear as mudanças, eles confiam em mutações para isso. Alterações "fora do limite" no estado são, portanto, invisíveis para elas.
Ações, como mutações, também residem no módulo da loja e podem receber o
state
objeto. O que implica que eles também poderiam sofrer uma mutação direta. Então, qual é o sentido de ter os dois? Se argumentamos que as mutações precisam ser pequenas e simples, isso implica que precisamos de um meio alternativo para abrigar uma lógica de negócios mais elaborada. Ações são os meios para fazer isso. E, como estabelecemos anteriormente, o vue-devtools e os plugins estão cientes das mudanças por meio do Mutations. Para manter a consistência, devemos continuar usando o Mutations em nossas ações. Além disso, como as ações devem ser abrangentes e que a lógica que elas encapsulam pode ser assíncrona, faz sentido que as ações também sejam simplesmente assíncronas desde o início.Muitas vezes, é enfatizado que as ações podem ser assíncronas, enquanto as mutações normalmente não são. Você pode decidir ver a distinção como uma indicação de que mutações devem ser usadas para qualquer coisa síncrona (e ações para qualquer coisa assíncrona); no entanto, você terá algumas dificuldades se, por exemplo, precisar cometer mais de uma mutação (de forma síncrona) ou se precisar trabalhar com um Getter a partir de suas mutações, pois as funções de mutação não recebem Getters nem Mutações como argumentos ...
... o que leva a uma pergunta interessante.
Ainda não encontrei uma resposta satisfatória para esta pergunta. Eu vi algumas explicações da equipe principal que achei discutíveis na melhor das hipóteses. Se eu resumir seu uso, os Getters devem ser extensões computadas (e geralmente armazenadas em cache) para o estado. Em outras palavras, eles ainda são basicamente o estado, embora exijam alguma computação inicial e normalmente são somente leitura. É assim que são incentivados a serem usados.
Portanto, impedir que o Mutations acesse diretamente o Getters significa que agora é necessário um de três itens, se precisarmos acessar do antigo alguma funcionalidade oferecida pelo último: (1) os cálculos de estado fornecidos pelo Getter são duplicados em algum lugar acessível para a Mutação (mau cheiro) ou (2) o valor calculado (ou o próprio Getter relevante) é passado como um argumento explícito para a Mutação (descolada), ou (3) a lógica do Getter é duplicada diretamente dentro da Mutação , sem o benefício adicional do armazenamento em cache, conforme fornecido pelo Getter (fedor).
A seguir, é apresentado um exemplo de (2), que na maioria dos cenários que encontrei parece a opção "menos ruim".
Para mim, o exposto acima parece não apenas um pouco complicado, mas também um pouco "vazante", uma vez que parte do código presente na Ação está claramente escorrendo da lógica interna da Mutação.
Na minha opinião, isso é uma indicação de um compromisso. Acredito que permitir que o Mutations receba automaticamente Getters apresenta alguns desafios. Pode ser tanto para o design do próprio Vuex, como para o ferramental (vue-devtools et al), ou para manter alguma compatibilidade com versões anteriores ou uma combinação de todas as possibilidades declaradas.
O que eu não acredito é que passar Getters para suas Mutações é necessariamente um sinal de que você está fazendo algo errado. Eu vejo isso simplesmente como "corrigir" uma das falhas do framework.
fonte
computed
saída. Eles são somente leitura. Uma maneira melhor de ver as mutações pode ser remover as queif else
você possui. Os documentos da vuex dizem que você pode abrigar mais de 1commit
em uma ação. Portanto, seria lógico supor que você poderia cometer certa mutação, dependendo da lógica. Eu vejo as ações como uma maneira de ditar qual mutação será disparada.Penso que a resposta do TLDR é que as mutações devem ser síncronas / transacionais. Portanto, se você precisar executar uma chamada Ajax ou qualquer outro código assíncrono, precisará fazer isso em uma Ação e, em seguida, confirmar uma mutação depois, para definir o novo estado.
fonte
As principais diferenças entre ações e mutações:
fonte
De acordo com
docs
As ações são semelhantes às mutações , as diferenças são as seguintes:
Considere o seguinte trecho.
fonte
Isenção de responsabilidade - Eu comecei a usar vuejs apenas, portanto, sou apenas eu que extrapolo a intenção do design.
A depuração da máquina do tempo usa instantâneos do estado e mostra uma linha do tempo de ações e mutações. Em teoria, poderíamos ter
actions
acompanhado uma gravação de criadores e criadores de estados para descrever de forma síncrona a mutação. Mas então:mutations
transações, mas podemos dizer que a transação precisa ser aprimorada, em vez de ser uma condição de corrida nas ações. Mutações anônimas dentro de uma ação poderiam ressurgir com mais facilidade esses tipos de erros, porque a programação assíncrona é frágil e difícil.Compare o seguinte log de transações com mutações nomeadas.
Com um log de transações que não possui mutações nomeadas:
Espero que você possa extrapolar a partir desse exemplo a potencial complexidade adicionada em mutações assíncronas e anônimas dentro de ações.
https://vuex.vuejs.org/en/mutations.html
fonte
Mutações:
Ações:
Em Redux Way
Por que ambos ??
Quando o aplicativo crescer, a codificação e as linhas aumentarem. Dessa vez, você precisará lidar com a lógica em Ações, não nas mutações, porque as mutações são a única autoridade para alterar o estado, e deve estar o mais limpo possível.
fonte
Isso também me confundiu, então fiz uma demonstração simples.
component.vue
store.js
Depois de pesquisar isso, a conclusão a que cheguei é que as mutações são uma convenção focada apenas na alteração de dados para separar melhor as preocupações e melhorar o registro antes e depois dos dados atualizados. Considerando que as ações são uma camada de abstração que lida com a lógica de nível superior e, em seguida, chama as mutações adequadamente
fonte
1.De documentos :
As ações podem conter operações assíncronas, mas a mutação não pode.
2. Invocamos a mutação, podemos mudar o estado diretamente. e também podemos, na ação de mudar de estado, assim:
as ações foram projetadas para lidar com mais outras coisas, podemos fazer muitas coisas lá (podemos usar operações assíncronas) e depois mudar o estado por mutação de despacho lá.
fonte
Porque não há estado sem mutações! Quando confirmada - é executada uma parte da lógica que altera o estado de maneira previsível. As mutações são a única maneira de definir ou alterar o estado (para que não haja mudanças diretas!) E, além disso, elas devem ser síncronas. Esta solução gera uma funcionalidade muito importante: as mutações estão registrando no devtools. E isso fornece uma excelente legibilidade e previsibilidade!
Mais uma coisa - ações. Como já foi dito - as ações cometem mutações. Portanto, eles não alteram a loja e não é necessário que eles sejam síncronos. Mas eles podem gerenciar uma parte extra da lógica assíncrona!
fonte
Pode parecer desnecessário ter uma camada extra
actions
apenas para chamar omutations
, por exemplo:Então, se chamando
actions
chamadaslogout
, por que não chamar a própria mutação?A idéia inteira de uma ação é chamar várias mutações de dentro de uma ação ou fazer uma solicitação do Ajax ou qualquer tipo de lógica assíncrona que você possa imaginar.
Eventualmente, podemos ter ações que fazem várias solicitações de rede e eventualmente chamam muitas mutações diferentes.
Por isso, tentamos coisas tanto a complexidade do nosso
Vuex.Store()
possível em nossosactions
e isso deixa a nossamutations
,state
egetters
mais limpo e simples e está em consonância com o tipo de modularidade que torna bibliotecas como Vue e reagir popular.fonte
Uso o Vuex profissionalmente há cerca de 3 anos, e aqui está o que acho que descobri sobre as diferenças essenciais entre ações e mutações, como você pode se beneficiar de usá-las bem juntas e como pode tornar sua vida mais difícil se você não use bem.
O principal objetivo do Vuex é oferecer um novo padrão para controlar o comportamento do seu aplicativo: Reatividade. A idéia é descarregar a orquestração do estado do seu aplicativo em um objeto especializado: uma loja. Fornece convenientemente métodos para conectar seus componentes diretamente aos dados da sua loja, para serem utilizados conforme sua conveniência. Isso permite que seus componentes se concentrem no trabalho deles: definir um modelo, estilo e comportamento básico do componente para apresentar ao usuário. Enquanto isso, a loja lida com a carga pesada de dados.
Essa não é apenas a única vantagem desse padrão. O fato de as lojas serem uma fonte única de dados para toda a sua aplicação oferece um grande potencial de reutilização desses dados em muitos componentes. Esse não é o primeiro padrão que tenta resolver esse problema da comunicação entre componentes, mas o ponto alto é que obriga a implementar um comportamento muito seguro para seu aplicativo, proibindo basicamente seus componentes de modificar o estado desses dados compartilhados e forçá-lo a usar "pontos de extremidade públicos" para solicitar alterações.
A ideia básica é esta:
Dito isto, a mágica começa quando começamos a projetar nosso aplicativo dessa maneira. Por exemplo:
No final, temos uma experiência do usuário considerada "reativa". Da perspectiva de nosso usuário, o item foi excluído imediatamente. Na maioria das vezes, esperamos que nossos pontos de extremidade funcionem, então isso é perfeito. Quando falha, ainda temos algum controle sobre como nosso aplicativo reagirá , porque separamos com êxito a preocupação do estado de nosso aplicativo front-end com os dados reais.
Você nem sempre precisa de uma loja, lembre-se. Se você achar que está escrevendo lojas que se parecem com isso:
Para mim, parece que você está apenas usando o armazenamento como um armazenamento de dados e talvez esteja perdendo o aspecto de reatividade, ao não permitir que ele também assuma o controle de variáveis às quais seu aplicativo reage. Basicamente, você pode e provavelmente deve descarregar algumas linhas de código escritas em seus componentes para suas lojas.
fonte