Vuex Ação vs Mutações

173

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?

Kobi
fonte
2
Veja "Sobre as ações", eu acho: vuex.vuejs.org/en/mutations.html#on-to-actions
Roy J
discussão relacionada: github.com/vuejs/vuex/issues/587
chuck911
1
Você não pode alterar diretamente o estado da loja. A única maneira de alterar o estado de uma loja é cometendo mutações explicitamente. Para isso, precisamos de ações para cometer mutações.
precisa saber é o seguinte
1
@SureshSapkota essa afirmação é muito confusa, pois ambos mutationse actionssã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.
Graham
1
Mutações, como o nome sugere, são usadas para modificar / modificar seu objeto de estado. As ações são bastante semelhantes às mutações, mas, em vez de mutar o estado, as ações cometem mutações. As ações podem conter qualquer código assíncrono arbitrário ou lógica de negócios . A Vuex recomenda que o objeto state só seja mutado dentro das funções Mutation. Também é recomendável não executar nenhum código pesado ou de bloqueio nas funções Mutation, pois é de natureza síncrona .
Emmanuel Neni 22/06

Respostas:

221

Pergunta 1 : Por que os desenvolvedores do Vuejs decidiram fazer dessa maneira?

Responda:

  1. Quando o seu aplicativo se tornar grande e quando houver vários desenvolvedores trabalhando neste projeto, você encontrará o "estado gerencia" (especialmente o "estado global"), que se tornará cada vez mais complicado.
  2. A maneira vuex (assim como o Redux no react.js ) oferece um novo mecanismo para gerenciar estado, manter estado e "salvar e rastreável" (isso significa que toda ação que modifica o estado pode ser rastreada pela ferramenta de depuração: vue-devtools )

Pergunta 2 : Qual a diferença entre "ação" e "mutação"?

Vamos ver a explicação oficial primeiro:

Mutações:

Mutações Vuex são essencialmente eventos: cada mutação tem um nome e um manipulador.

import Vuex from 'vuex'

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

Ações: Ações são apenas funções que despacham mutações.

// 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)
}

Aqui está a minha explicação do acima:

  • mutação é a única maneira de modificar o estado
  • mutação não se preocupa com lógica de negócios, apenas se preocupa com "estado"
  • ação é lógica de negócios
  • A ação pode despachar mais de uma mutação por vez, apenas implementa a lógica de negócios, não se preocupa com a alteração de dados (que gerencia por mutação)
Kaicui
fonte
80
O fato de uma ação "ser a lógica de negócios" e poder despachar várias mutações ao mesmo tempo é útil. Essa é a resposta que eu estava procurando. Obrigado.
Kobi
11
você está dizendo que "envia uma mutação". Não é o texto correto que você COMPROMETE uma mutação?
ProblemsOfSumit
4
Você envia ações e confirma mutações.
Eirik
4
Se o envio não funcionar mais no vue 2.0 para mutação, é necessário confirmar uma mutação na ação.
SKLTFZ 21/02
18
@Kaicui Esta resposta está faltando uma observação sobre as mutações sempre síncronas e as ações potencialmente assíncronas. Fora isso, uma boa resposta!
decates 10/10
58

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.

Bas
fonte
2
isso realmente responde a uma pergunta que eu faria, sobre como o exemplo todomvc não faz uso de ações.
sksallaj
7
'Você não precisa de ações se suas operações são síncronas' : Isso não é verdade: você fazer ações precisam se quiser compor múltiplas mutações do mesmo módulo, porque você não pode chamar outra ação a partir de uma ação.
Raymundus
1
O follow-up óbvio para esta resposta seria "então porque não basta ter ações e livrar-se de mutações"
Michael Mrozek
34

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.

Por que passar pelo clichê em primeiro lugar? Por que não mudar de estado diretamente nos componentes?

A rigor, você pode alterar statediretamente os componentes. O stateé apenas um objeto JavaScript e não há nada mágico que reverta as alterações feitas nele.

// Yes, you can!
this.$store.state['products'].push(product)

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.

// so we go from this
this.$store.state['products'].push(product)

// to this
this.$store.commit('addProduct', {product})

...
// and in store
addProduct(state, {product}){
    state.products.push(product)
}
...

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.

Então mutations, actionsqual é a diferença, afinal?

Ações, como mutações, também residem no módulo da loja e podem receber o stateobjeto. 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.

Por que as mutações não recebem Getters?

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".

state:{
    shoppingCart: {
        products: []
    }
},

getters:{
    hasProduct(state){
        return function(product) { ... }
    }
}

actions: {
    addProduct({state, getters, commit, dispatch}, {product}){

        // all kinds of business logic goes here

        // then pull out some computed state
        const hasProduct = getters.hasProduct(product)
        // and pass it to the mutation
        commit('addProduct', {product, hasProduct})
    }
}

mutations: {
    addProduct(state, {product, hasProduct}){ 
        if (hasProduct){
            // mutate the state one way
        } else {
            // mutate the state another way 
        }
    }
}

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.

Michael Ekoka
fonte
1
Para mim, essa é a melhor resposta. Somente depois de ler, tive esse "clique" que você sente quando sentiu que entendeu alguma coisa.
Robert Kusznier 6/07/19
Getters são essencialmente de computedsaída. Eles são somente leitura. Uma maneira melhor de ver as mutações pode ser remover as que if elsevocê possui. Os documentos da vuex dizem que você pode abrigar mais de 1 commitem 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.
Tamb
@Tamb: State e Getters oferecem dados contextuais. Faz sentido que eles sejam consultados antes de decidir como modificar o Estado. Quando essas informações podem ser obtidas inteiramente do Estado, faz sentido que toda a lógica seja encapsulada dentro de uma única Mutação, uma vez que ela tem acesso ao Estado. Este é o procedimento operacional padrão para um levantador. O que faz menos sentido é ter uma abordagem radicalmente diferente, simplesmente porque agora precisamos consultar um Getter para obter informações semelhantes.
Michael Ekoka
@Tamb: O que você está sugerindo é que, quando precisamos consultar o Getters, devemos alterar o padrão acima e mover a lógica de seleção para uma Ação proxy que possa acessar o Getter e colar várias pequenas mutações idiotas. Funciona, mas ainda é tortuoso e não aborda o mau cheiro a que estou me referindo na minha resposta, apenas o move para outro lugar.
Michael Ekoka
Os documentos dizem que para usar getters quando você precisar calcular o estado. Por isso, parecia correto o dia em que eles são semelhantes às propriedades calculadas. Idk o que você está dizendo, dizendo que a ação pode colar mutações. Os documentos dizem claramente para colocar a lógica de negócios dentro das ações.
Tamb
15

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.

Noah Namey
fonte
1
Isso parece um resumo da documentação; com o qual não há nada errado. No entanto, o problema com esta resposta é que o que afirma não é necessariamente verdadeiro. É possível modificar o estado dentro de uma mutação ao chamar uma função assíncrona / AJAX, que pode ser alterada no retorno de chamada completo. Eu acho que é isso que está causando tanta confusão sobre por que as ações devem ser usadas para as melhores práticas de desenvolvimento ao trabalhar com o Vuex. Eu sei que isso certamente foi uma fonte de confusão para mim quando comecei a trabalhar com a Vuex.
precisa saber é o seguinte
8

As principais diferenças entre ações e mutações:

  1. Ações internas você pode executar código assíncrono, mas não em mutações. Portanto, use ações para código assíncrono, caso contrário, use mutações.
  2. Dentro de ações, você pode acessar getters, estado, mutações (comprometendo-as), ações (despachando-as) em mutações, que você pode acessar o estado. Portanto, se você deseja acessar apenas o estado, use mutações, caso contrário, use ações.
roli roli
fonte
5

De acordo com docs

As ações são semelhantes às mutações , as diferenças são as seguintes:

  • Em vez de mudar o estado, as ações cometem mutações.
  • As ações podem conter operações assíncronas arbitrárias .

Considere o seguinte trecho.

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

Os manipuladores de ação ( incremento ) recebem um objeto de contexto que expõe o mesmo conjunto de métodos / propriedades na instância do armazenamento, para que você possa chamar context.commit para confirmar uma mutação ou acessar o estado e os getters via context.state e context.getters

Abdullah Khan
fonte
1
é possível chamar da função 'mutação', um método do componente vuejs?
Alberto Acuña
@ AlbertoAcuña Eu tenho a mesma pergunta, porque quando tento fazer isso, gera um erro que a mutação local é indefinida.
Rutwick Gangurde 26/02
5

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 actionsacompanhado uma gravação de criadores e criadores de estados para descrever de forma síncrona a mutação. Mas então:

  • Teríamos entradas impuras (resultados assíncronos) que causavam os setters e getters. Seria difícil seguir isso logicamente, e diferentes criadores e geradores assíncronos podem surpreendentemente interagir. Isso ainda pode acontecer commutations 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.
  • O log de transações seria difícil de ler porque não haveria nome para as alterações de estado. Seria muito mais parecido com código e menos inglês, perdendo os agrupamentos lógicos de mutações.
  • Pode ser mais complicado e menos eficiente instrumentar a gravação de qualquer mutação em um objeto de dados, em vez de agora onde existem pontos de diferença definidos de forma síncrona - antes e depois da chamada da função de mutação. Não tenho certeza do tamanho de um problema.

Compare o seguinte log de transações com mutações nomeadas.

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

Com um log de transações que não possui mutações nomeadas:

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

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

Agora imagine que estamos depurando o aplicativo e observando os logs de mutação do devtool. Para cada mutação registrada, o devtool precisará capturar um instantâneo "antes" e "depois" do estado. No entanto, o retorno de chamada assíncrono dentro da mutação de exemplo acima torna isso impossível: o retorno de chamada ainda não é chamado quando a mutação é confirmada e não há como o devtool saber quando o retorno de chamada será realmente chamado - qualquer mutação de estado executada no retorno de chamada é essencialmente não rastreável!

ubershmekel
fonte
4

Mutações:

Can update the state. (Having the Authorization to change the state).

Ações:

Actions are used to tell "which mutation should be triggered"

Em Redux Way

Mutations are Reducers
Actions are Actions

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.

Gopinath Kaliappan
fonte
2

Isso também me confundiu, então fiz uma demonstração simples.

component.vue

<template>
    <div id="app">
        <h6>Logging with Action vs Mutation</h6>
        <p>{{count}}</p>
        <p>
            <button @click="mutateCountWithAsyncDelay()">Mutate Count directly with delay</button>
        </p>
        <p>
            <button @click="updateCountViaAsyncAction()">Update Count via action, but with delay</button>
        </p>
        <p>Note that when the mutation handles the asynchronous action, the "log" in console is broken.</p>
        <p>When mutations are separated to only update data while the action handles the asynchronous business
            logic, the log works the log works</p>
    </div>
</template>

<script>

        export default {
                name: 'app',

                methods: {

                        //WRONG
                        mutateCountWithAsyncDelay(){
                                this.$store.commit('mutateCountWithAsyncDelay');
                        },

                        //RIGHT
                        updateCountViaAsyncAction(){
                                this.$store.dispatch('updateCountAsync')
                        }
                },

                computed: {
                        count: function(){
                                return this.$store.state.count;
                        },
                }

        }
</script>

store.js

import 'es6-promise/auto'
import Vuex from 'vuex'
import Vue from 'vue';

Vue.use(Vuex);

const myStore = new Vuex.Store({
    state: {
        count: 0,
    },
    mutations: {

        //The WRONG way
        mutateCountWithAsyncDelay (state) {
            var log1;
            var log2;

            //Capture Before Value
            log1 = state.count;

            //Simulate delay from a fetch or something
            setTimeout(() => {
                state.count++
            }, 1000);

            //Capture After Value
            log2 = state.count;

            //Async in mutation screws up the log
            console.log(`Starting Count: ${log1}`); //NRHG
            console.log(`Ending Count: ${log2}`); //NRHG
        },

        //The RIGHT way
        mutateCount (state) {
            var log1;
            var log2;

            //Capture Before Value
            log1 = state.count;

            //Mutation does nothing but update data
            state.count++;

            //Capture After Value
            log2 = state.count;

            //Changes logged correctly
            console.log(`Starting Count: ${log1}`); //NRHG
            console.log(`Ending Count: ${log2}`); //NRHG
        }
    },

    actions: {

        //This action performs its async work then commits the RIGHT mutation
        updateCountAsync(context){
            setTimeout(() => {
                context.commit('mutateCount');
            }, 1000);
        }
    },
});

export default myStore;

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

Nathaniel Rink
fonte
0

1.De documentos :

As ações são semelhantes às mutações, as diferenças são as seguintes:

  • Em vez de mudar o estado, as ações cometem mutações.
  • As ações podem conter operações assíncronas arbitrárias.

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:

actions: {
  increment (store) {
    // do whatever ... then change the state
    store.dispatch('MUTATION_NAME')
  }
}

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á.

aeronave
fonte
0

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!

Sumit Patel
fonte
0

Pode parecer desnecessário ter uma camada extra actionsapenas para chamar o mutations, por exemplo:

const actions = {
  logout: ({ commit }) => {
    commit("setToken", null);
  }
};

const mutations = {
  setToken: (state, token) => {
    state.token = token;
  }
};

Então, se chamando actionschamadas logout, 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 nossos actionse isso deixa a nossa mutations, statee gettersmais limpo e simples e está em consonância com o tipo de modularidade que torna bibliotecas como Vue e reagir popular.

Daniel
fonte
0

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:

  • A loja possui um estado interno, que nunca deve ser acessado diretamente pelos componentes (o mapState é efetivamente banido)
  • A loja possui mutações, que são modificações síncronas para o estado interno. O único trabalho de uma mutação é modificar o estado. Eles devem ser chamados apenas de uma ação. Eles devem ser nomeados para descrever as coisas que aconteceram com o estado (ORDER_CANCELED, ORDER_CREATED). Mantenha-os curtos e doces. Você pode percorrê-los usando a extensão do navegador Vue Devtools (também é ótimo para depuração!)
  • A loja também possui ações, que devem ser assíncronas ou retornar uma promessa. São as ações que seus componentes chamarão quando quiserem modificar o estado do aplicativo. Eles devem ser nomeados com ações orientadas para negócios (verbos, ou seja, cancelOrder, createOrder). É aqui que você valida e envia suas solicitações. Cada ação pode chamar confirmações diferentes em etapas diferentes, se for necessário alterar o estado.
  • Por fim, a loja possui getters, que são usados ​​para expor seu estado a seus componentes. Espere que eles sejam muito usados ​​em muitos componentes à medida que seu aplicativo se expande. O Vuex armazena em cache os getters fortemente para evitar ciclos de computação inúteis (desde que você não adicione parâmetros ao seu getter - tente não usar parâmetros), portanto, não hesite em usá-los extensivamente. Apenas certifique-se de fornecer nomes que descrevam o mais próximo possível do estado em que o aplicativo está atualmente.

Dito isto, a mágica começa quando começamos a projetar nosso aplicativo dessa maneira. Por exemplo:

  • Temos um componente que oferece uma lista de pedidos ao usuário com a possibilidade de excluir esses pedidos
  • Os componentes mapearam um getter de loja (deletableOrders), que é uma matriz de objetos com ids
  • O componente possui um botão em cada linha de pedidos, e seu clique é mapeado para uma ação da loja (deleteOrder) que passa o objeto do pedido para ele (que, lembraremos, vem da própria lista da loja)
  • A ação deleteOrder da loja faz o seguinte:
    • valida a exclusão
    • ele armazena o pedido para excluir temporariamente
    • confirma a mutação ORDER_DELETED com a ordem
    • envia a chamada da API para realmente excluir o pedido (sim, APÓS modificar o estado!)
    • aguarda o término da chamada (o estado já está atualizado) e, em caso de falha, chamamos a mutação ORDER_DELETE_FAILED com a ordem que mantivemos anteriormente.
  • A mutação ORDER_DELETED simplesmente removerá o pedido fornecido da lista de pedidos excluídos (que atualizará o getter)
  • A mutação ORDER_DELETE_FAILED simplesmente a coloca de volta e modifica o estado para notificar o erro (outro componente, notificação de erro, estaria rastreando esse estado para saber quando se exibir)

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:

export default {
  state: {
    orders: []
  },
  mutations: {
    ADD_ORDER (state, order) {
       state.orders.push(order)
    },
    DELETE_ORDER (state, orderToDelete) {
       state.orders = state.orders.filter(order => order.id !== orderToDelete.id)
    }
  },
  actions: {
    addOrder ({commit}, order) {
      commit('ADD_ORDER', order)
    },
    deleteOrder ({commit}, order) {
      commit('DELETE_ORDER', order)
    }
  },
  getters: {
    orders: state => state.orders
  }
}

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.

Alex
fonte