Vuex Action против мутаций

173

В Vuex, какова логика наличия как «действий», так и «мутаций»?

Я понимаю логику компонентов, не способных изменять состояние (что кажется разумным), но наличие как действий, так и мутаций похоже на то, что вы пишете одну функцию для запуска другой функции, чтобы затем изменить состояние.

В чем разница между «действиями» и «мутациями», как они работают вместе, и более того, мне любопытно, почему разработчики Vuex решили сделать это таким образом?

Коби
источник
2
См. «По действиям», я думаю: vuex.vuejs.org/en/mutations.html#on-to-actions
Рой J
соответствующее обсуждение: github.com/vuejs/vuex/issues/587
chuck911
1
Вы не можете напрямую изменить состояние магазина. Единственный способ изменить состояние магазина - это явно зафиксировать мутации. Для этого нам нужны действия, чтобы совершить мутации.
Суреш Сапкота
1
@SureshSapkota это утверждение очень сбивает с толку, так как оба mutationsи actionsопределены в документации vuex как методы изменения состояния. Вам не нужно действие, чтобы совершить мутацию.
Грэм
1
Мутации, как следует из названия, используются для изменения / изменения объекта состояния. Действия очень похожи на мутации, но вместо того, чтобы изменять состояние, действия совершают мутации. Действия могут содержать любой произвольный асинхронный код или бизнес-логику . Vuex рекомендует, чтобы объект состояния был видоизменен только внутри функций мутации. Также рекомендуется не запускать какой-либо тяжелый или блокирующий код внутри функций Mutation, поскольку он является синхронным по своей природе .
Эммануэль Нени

Ответы:

221

Вопрос 1 : Почему разработчики Vuejs решили сделать это таким образом?

Ответ:

  1. Когда ваше приложение станет большим, и когда над этим проектом будет работать несколько разработчиков, вы обнаружите, что «управление состоянием» (особенно «глобальное состояние») будет становиться все более сложным.
  2. Способ vuex (так же, как и в Redux вact.js ) предлагает новый механизм для управления состоянием, сохранения состояния и «сохранения и отслеживания» (это означает, что каждое действие, которое изменяет состояние, может отслеживаться инструментом отладки: vue-devtools )

Вопрос 2 : В чем разница между «действием» и «мутацией»?

Давайте сначала посмотрим официальное объяснение:

Мутации:

Мутации Vuex по сути являются событиями: каждая мутация имеет имя и обработчик.

import Vuex from 'vuex'

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

Действия: Действия - это просто функции, которые отправляют мутации.

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

Вот мое объяснение вышесказанного:

  • мутация - единственный способ изменить состояние
  • мутация не заботится о бизнес-логике, она просто заботится о «состоянии»
  • действие это бизнес логика
  • действие может отправлять более 1 мутации за раз, оно просто реализует бизнес-логику, не заботится об изменении данных (которые управляются мутацией)
Kaicui
источник
80
Полезно то, что действие «является бизнес-логикой» и может отправлять несколько мутаций одновременно. Это ответ, который я искал. Спасибо.
Коби,
11
Вы, чуваки, говорите, что «отправили мутацию». Разве не правильная формулировка, что вы совершаете мутацию?
Задачи
4
Вы отправляете действия и совершаете мутации.
eirik
4
диспетчеризация больше не работает в vue 2.0 для мутации, вам нужно зафиксировать мутацию в действии.
SKLTFZ
18
@Kaicui В этом ответе отсутствует примечание о том, что мутации всегда являются синхронными, а действия потенциально могут быть асинхронными. Кроме этого, хороший ответ!
17
58

Мутации синхронны, тогда как действия могут быть асинхронными.

Иными словами, вам не нужны действия, если ваши операции синхронны, в противном случае реализуйте их.

Bas
источник
2
это фактически отвечает на вопрос, который я собирался задать, о том, как пример todomvc не использует действия.
Сксаллай
7
«Вам не нужно действие , если ваши действия являются синхронными» : Это не так: вы делаете потребность действие , если вы хотите создавать множественные мутации из одного модуля, потому что вы не можете вызвать другое действие от действия.
Раймунд
1
Очевидным продолжением этого ответа будет «тогда почему бы просто не иметь действий и избавиться от мутаций»
Майкл
34

Я считаю, что понимание мотиваций, стоящих за мутациями и действиями, позволяет лучше судить о том, когда использовать, что и как. Это также освобождает программиста от бремени неопределенности в ситуациях, когда «правила» становятся нечеткими. Немного рассуждая об их соответствующих целях, я пришел к выводу, что, хотя могут определенно быть неправильные способы использования действий и мутаций, я не думаю, что существует канонический подход.

Давайте сначала попробуем понять, почему мы даже проходим либо Мутации, либо Действия.

Зачем идти по шаблону в первую очередь? Почему бы не изменить состояние непосредственно в компонентах?

Строго говоря, вы можете изменить stateнепосредственно из ваших компонентов. Это stateпросто объект JavaScript, и нет ничего волшебного, что могло бы отменить изменения, которые вы внесли в него.

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

Однако, делая это, вы разбрасываете мутации своего состояния повсюду. Вы теряете возможность просто открыть единственный модуль, в котором находится состояние, и сразу увидеть, какие операции могут быть применены к нему. Централизованные мутации решают это, хотя и за счет некоторого шаблона.

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

Я думаю, что если вы замените что-то короткое на шаблон, вы захотите, чтобы шаблон также был маленьким. Поэтому я предполагаю, что мутации должны быть очень тонкими обертками вокруг нативных операций над состоянием, почти без бизнес-логики. Другими словами, мутации предназначены для использования в основном как сеттеры.

Теперь, когда вы централизовали свои мутации, у вас есть лучший обзор изменений вашего состояния, и поскольку ваш инструмент (vue-devtools) также знает об этом месте, это облегчает отладку. Также стоит помнить, что многие плагины Vuex не отслеживают состояние напрямую, чтобы отслеживать изменения, а скорее полагаются на мутации. Таким образом, изменения состояния невидимы для них.

Итак mutations, в actionsчем разница в любом случае?

Действия, такие как мутации, также находятся в модуле магазина и могут получать stateобъект. Что подразумевает, что они могут также изменить его напрямую. Так какой смысл иметь оба? Если мы рассуждаем о том, что мутации должны быть небольшими и простыми, это означает, что нам нужны альтернативные средства для размещения более сложной бизнес-логики. Действия являются средством для этого. И поскольку, как мы установили ранее, vue-devtools и плагины знают об изменениях посредством мутаций, чтобы оставаться последовательными, мы должны продолжать использовать мутации из наших действий. Кроме того, поскольку все действия должны охватывать все объекты, а логика, которую они инкапсулируют, может быть асинхронной, имеет смысл, что действия с самого начала просто делались бы асинхронными.

Часто подчеркивается, что действия могут быть асинхронными, а мутации - нет. Вы можете решить рассматривать различие как указание на то, что мутации должны использоваться для чего-то синхронного (и действия для чего-либо асинхронного); тем не менее, вы столкнетесь с некоторыми трудностями, если, например, вам нужно будет зафиксировать более одной мутации (синхронно) или вам нужно работать с геттером из ваших мутаций, поскольку функции мутации не получают ни геттеры, ни мутации в качестве аргументов ...

... что приводит к интересному вопросу.

Почему мутации не получают геттеры?

Я еще не нашел удовлетворительного ответа на этот вопрос. Я видел некоторые объяснения со стороны основной команды, что я нашел спор в лучшем случае. Если я резюмирую их использование, то получатели должны быть вычислены (и часто кэшированы) расширениями состояния. Другими словами, они в основном все еще находятся в состоянии, хотя и требуют предварительных вычислений и обычно доступны только для чтения. По крайней мере, так их поощряют.

Таким образом, предотвращение прямого доступа мутаций к геттерам означает, что теперь необходима одна из трех вещей, если нам необходимо получить доступ от первого к некоторым функциональным возможностям, предлагаемым последним: (1) либо вычисления состояний, предоставляемые геттером, дублируются где-то, что доступно в Мутацию (неприятный запах), или (2) вычисленное значение (или соответствующий сам Геттер) передается в качестве явного аргумента Мутации (фанки), или (3) сама логика Геттера дублируется непосредственно в Мутации без дополнительного преимущества кэширования, предоставляемого Getter (stench).

Ниже приведен пример (2), который в большинстве сценариев, с которыми я столкнулся, кажется «наименее плохим» вариантом.

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

На мой взгляд, вышесказанное кажется не только немного запутанным, но и несколько «утечкой», поскольку часть кода, присутствующего в Action, явно вытекает из внутренней логики Mutation.

На мой взгляд, это показатель компромисса. Я считаю, что разрешение мутациям автоматически получать геттеров сопряжено с некоторыми трудностями. Это может быть либо дизайн самого Vuex, либо инструментарий (vue-devtools et al), либо сохранение некоторой обратной совместимости, либо некоторая комбинация всех заявленных возможностей.

Я не верю в то, что передача Геттеров своим Мутациям сама по себе является признаком того, что вы делаете что-то не так. Я считаю это просто «исправлением» одного из недостатков фреймворка.

Майкл Экока
источник
1
Для меня это лучший ответ. Только после прочтения я почувствовал этот «щелчок», когда почувствовал, что что-то понял.
Роберт Кушнье
Геттеры по сути computedвыходной. Они только для чтения. Более хорошим способом просмотра мутаций может быть удаление того, if elseчто у вас есть. Документы Vuex говорят, что вы можете разместить более 1 commitвнутри действия. Поэтому было бы логично предположить, что вы можете совершить определенную мутацию в зависимости от логики. Я рассматриваю действия как способ диктовать, какую мутацию запустить.
Tamb
@Tamb: State и Getters предлагают контекстные данные. Имеет смысл, что они будут опрошены, прежде чем решить, как изменить государство. Когда эта информация может быть получена полностью из государства, имеет смысл, что вся логика будет заключена в одну мутацию, поскольку она имеет доступ к государству. Это стандартная процедура работы для сеттера. Менее целесообразно иметь принципиально иной подход просто потому, что теперь нам нужно запросить у Getter аналогичную информацию.
Майкл Экока
@Tamb: То, что вы предлагаете, заключается в том, что, когда нам нужно запросить геттеры, мы должны изменить вышеуказанный шаблон и переместить логику выбора в прокси-действие, которое может получить доступ к геттеру и может склеить кучу крошечных глупых мутаций. Он работает, но он все еще обходной и не устраняет неприятный запах, о котором я говорю в своем ответе, он просто перемещает его куда-то еще.
Майкл Экока
Документы говорят, что использовать геттеры, когда вам нужно вычислить состояние. Так что сегодня казалось правильным, что они похожи на вычисленные свойства. Поймите, что вы получаете, говоря, что действие может склеить мутации. Документы ясно говорят, чтобы поместить бизнес-логику в действия.
Tamb
15

Я думаю, что ответ TLDR заключается в том, что мутации должны быть синхронными / транзакционными. Поэтому, если вам нужно выполнить Ajax-вызов или выполнить любой другой асинхронный код, вы должны сделать это в Action, а затем зафиксировать мутацию после, чтобы установить новое состояние.

Ной Нейми
источник
1
Это похоже на обобщение документации; с которым нет ничего плохого. Однако проблема с этим ответом состоит в том, что то, что он утверждает, не обязательно верно. Вы можете изменить состояние внутри мутации при вызове асинхронной функции / AJAX, которая затем может быть изменена при полном обратном вызове. Я думаю, что именно это и вызывает большую путаницу в том, почему при работе с Vuex следует использовать действия для лучшей практики разработки. Я знаю, что это было источником путаницы для меня, когда я начал работать с Vuex.
Erutan409
8

Основные различия между действиями и мутациями:

  1. Внутри действий вы можете запускать асинхронный код, но не в мутациях. Поэтому используйте действия для асинхронного кода, в противном случае используйте мутации.
  2. Внутри действий вы можете получить доступ к получателям, состоянию, мутациям (совершая их), действиям (отправляя их), в мутациях вы можете получить доступ к состоянию. Поэтому, если вы хотите получить доступ только к состоянию, используйте мутации, в противном случае используйте действия.
Роли Роли
источник
5

Согласно docs

Действия похожи на мутации , различия в том, что:

  • Вместо того, чтобы мутировать государство, действия совершают мутации.
  • Действия могут содержать произвольные асинхронные операции.

Рассмотрим следующий фрагмент.

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

Обработчики действий ( приращение ) получают объект контекста, который предоставляет тот же набор методов / свойств для экземпляра хранилища, поэтому вы можете вызвать context.commit для фиксации мутации или получить доступ к состоянию и получателям через context.state и context.getters

Абдулла Хан
источник
1
возможен вызов из функции 'мутации', метода из компонента vuejs?
Альберто Акунья
@ AlbertoAcuña У меня тот же вопрос, потому что, когда я пытаюсь это сделать, выдается ошибка, что локальная мутация не определена.
Рутвик Гангурде
5

Отказ от ответственности - я только начал использовать vuejs, так что это только я экстраполировал замысел проекта.

Отладка машины времени использует снимки состояния и показывает график действий и мутаций. В теории у нас могла бы быть только actionsзапись о методах установки и получения состояний, чтобы синхронно описывать мутацию. Но потом:

  • У нас были бы нечистые входные данные (асинхронные результаты), которые вызывали сеттеры и геттеры. За этим было бы трудно следовать логически, и разные асинхронные установщики и получатели могут удивительно взаимодействовать. Это все еще может произойти с mutationsтранзакциями, но тогда мы можем сказать, что транзакция должна быть улучшена, в отличие от того, чтобы быть гоночным условием в действиях. Анонимные мутации внутри действия могли бы легче выявлять подобные ошибки, потому что асинхронное программирование хрупко и сложно.
  • Журнал транзакций будет трудно читать, потому что не будет никакого имени для изменений состояния. Это было бы намного более похожим на код и менее английским, пропуская логические группировки мутаций.
  • Это может быть более хитрым и менее производительным для инструмента, записывающего любую мутацию в объекте данных, в отличие от того, где теперь есть синхронно определенные точки различия - до и после вызова функции мутации. Я не уверен, насколько это серьезная проблема.

Сравните следующий журнал транзакций с именованными мутациями.

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

С журналом транзакций, который не имеет именованных мутаций:

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

Я надеюсь, что вы можете извлечь из этого примера потенциальную дополнительную сложность в асинхронной и анонимной мутации внутри действий.

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

Теперь представьте, что мы отлаживаем приложение и просматриваем журналы мутаций devtool. Для каждой зарегистрированной мутации devtool должен будет делать снимки состояния «до» и «после». Однако асинхронный обратный вызов внутри приведенной выше мутации делает это невозможным: обратный вызов еще не вызывается при фиксации мутации, и у devtool нет возможности узнать, когда этот вызов будет фактически вызван - любая мутация состояния, выполненная в обратном вызове по сути не отслеживается!

ubershmekel
источник
4

Мутации:

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

Действия:

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

В Redux Way

Mutations are Reducers
Actions are Actions

Почему оба?

Когда приложение будет расти, кодирование и количество строк будут увеличиваться. В этот раз вы должны обрабатывать логику в действиях, а не в мутациях, потому что мутации являются единственным полномочием для изменения состояния, оно должно быть максимально чистым.

Гопинатх Калиаппан
источник
2

Это тоже смутило меня, поэтому я сделал простую демонстрацию.

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;

Изучив это, я пришел к выводу, что мутации - это соглашение, направленное только на изменение данных для лучшего разделения проблем и улучшения ведения журнала до и после обновленных данных. Принимая во внимание, что действия являются уровнем абстракции, который обрабатывает логику более высокого уровня и затем вызывает мутации соответственно

Натаниэль Ринк
источник
0

1. Из документов :

Действия похожи на мутации, различия в том, что:

  • Вместо того, чтобы мутировать государство, действия совершают мутации.
  • Действия могут содержать произвольные асинхронные операции.

Действия могут содержать асинхронные операции, но мутация не может.

2. Мы вызываем мутацию, мы можем изменить состояние напрямую. и мы также можем изменить действие следующим образом:

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

Действия предназначены для обработки большего количества других вещей, мы можем сделать там много вещей (мы можем использовать асинхронные операции), а затем изменить состояние, отправив туда мутацию.

самолет
источник
0

Потому что без мутаций нет государства! Когда зафиксировано - выполняется часть логики, которая изменяет состояние в предсказуемой форме. Мутации - это единственный способ установить или изменить состояние (так что прямых изменений нет!), И более того - они должны быть синхронными. Это решение обеспечивает очень важную функциональность: мутации входят в devtools. И это обеспечивает отличную читаемость и предсказуемость!

Еще одна вещь - действия. Как уже было сказано - действия совершают мутации. Таким образом, они не меняют магазин, и нет необходимости, чтобы они были синхронными. Но они могут управлять дополнительной частью асинхронной логики!

Сумит Патель
источник
0

Может показаться ненужным иметь дополнительный слой actionsдля вызова mutations, например:

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

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

Так что, если вы звоните actionsзвонки logout, почему бы не назвать саму мутацию?

Вся идея действия заключается в том, чтобы вызвать несколько мутаций изнутри одного действия или сделать Ajax-запрос или любую другую асинхронную логику, которую вы можете себе представить.

Мы можем в конечном итоге иметь действия, которые делают несколько сетевых запросов и в конечном итоге вызывают много разных мутаций.

Поэтому мы стараемся наполнить как можно больше сложностей от Vuex.Store()нашихactions , и это оставляет наш mutations, stateи gettersчище и прямолинейным и падает в соответствии с типом модульности , что делает библиотеки , как Vue и React популярны.

Даниил
источник
0

Я профессионально использую Vuex около 3 лет, и вот, как мне кажется, я выяснил о существенных различиях между действиями и мутациями, о том, как вы можете извлечь пользу из их совместного использования, и как вы можете сделать свою жизнь тяжелее, если вы не используйте это хорошо.

Основная цель Vuex - предложить новый шаблон для управления поведением вашего приложения: Реактивность. Идея состоит в том, чтобы переложить оркестровку состояния вашего приложения на специализированный объект: магазин. Он удобно предоставляет методы для подключения ваших компонентов непосредственно к данным вашего магазина, которые будут использоваться по своему усмотрению. Это позволяет вашим компонентам сосредоточиться на своей работе: определить шаблон, стиль и базовое поведение компонента для представления вашему пользователю. Между тем, магазин справляется с большой загрузкой данных.

Это не единственное преимущество этого паттерна. Тот факт, что хранилища являются единым источником данных для всего вашего приложения, дает большой потенциал повторного использования этих данных во многих компонентах. Это не первый шаблон, который пытается решить эту проблему межкомпонентного взаимодействия, но его преимущество состоит в том, что он заставляет вас реализовать очень безопасное поведение для вашего приложения, в основном запрещая вашим компонентам изменять состояние этих общих данных. и вместо этого заставьте его использовать «публичные конечные точки» для запроса изменений.

Основная идея заключается в следующем:

  • Хранилище имеет внутреннее состояние, к которому компоненты никогда не должны обращаться напрямую (mapState фактически заблокирован)
  • В магазине есть мутации, которые являются синхронной модификацией внутреннего состояния. Единственная работа мутации состоит в том, чтобы изменить состояние. Они должны быть вызваны только из действия. Они должны быть названы, чтобы описать вещи, которые произошли с состоянием (ORDER_CANCELED, ORDER_CREATED). Держите их короткими и сладкими. Вы можете пройти через них, используя расширение браузера Vue Devtools (оно также отлично подходит для отладки!)
  • В магазине также есть действия, которые должны быть асинхронными или возвращать обещание. Это действия, которые ваши компоненты будут вызывать, когда захотят изменить состояние приложения. Они должны быть названы с помощью бизнес-ориентированных действий (глаголы, например, cancelOrder, createOrder). Здесь вы подтверждаете и отправляете свои запросы. Каждое действие может вызывать разные коммиты на разных шагах, если требуется изменить состояние.
  • Наконец, в магазине есть геттеры, которые вы используете, чтобы представить свое состояние вашим компонентам. Ожидайте, что они будут интенсивно использоваться во многих компонентах по мере расширения вашего приложения. Vuex интенсивно кэширует геттеры, чтобы избежать бесполезных циклов вычислений (если вы не добавляете параметры в свой геттер - старайтесь не использовать параметры), поэтому не стесняйтесь их широко использовать. Просто убедитесь, что вы даете имена, которые как можно ближе описывают, в каком состоянии находится приложение.

Это сказанное, волшебство начинается, когда мы начинаем проектировать наше приложение таким способом. Например:

  • У нас есть компонент, который предлагает пользователю список заказов с возможностью их удаления.
  • Компоненты сопоставили получатель хранилища (deletableOrders), который представляет собой массив объектов с идентификаторами
  • Компонент имеет кнопку в каждой строке заказов, и его щелчок сопоставляется с действием магазина (deleteOrder), которое передает ему объект заказа (который, как мы помним, происходит из самого списка магазина)
  • Действие store deleteOrder выполняет следующие действия:
    • это подтверждает удаление
    • хранит заказ на временное удаление
    • он фиксирует мутацию ORDER_DELETED с порядком
    • он отправляет вызов API для фактического удаления заказа (да, ПОСЛЕ изменения состояния!)
    • он ожидает завершения вызова (состояние уже обновлено), а в случае неудачи мы вызываем мутацию ORDER_DELETE_FAILED с порядком, который мы сохранили ранее.
  • Мутация ORDER_DELETED просто удалит данный заказ из списка удаляемых заказов (который обновит получатель)
  • Мутация ORDER_DELETE_FAILED просто возвращает ее обратно и изменяет ее на состояние, чтобы уведомить об ошибке (другой компонент, уведомление об ошибке, будет отслеживать это состояние, чтобы знать, когда отображать себя)

В конце концов, у нас есть пользовательский опыт, который считается «реактивным». С точки зрения нашего пользователя, элемент был удален немедленно. В большинстве случаев мы ожидаем, что наши конечные точки будут просто работать, так что это идеально. Когда это терпит неудачу, у нас все еще есть некоторый контроль над тем, как наше приложение будет реагировать , потому что мы успешно отделили заботу о состоянии нашего интерфейсного приложения от реальных данных.

Помните, вам не всегда нужен магазин. Если вы обнаружите, что пишете магазины, которые выглядят так:

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

Мне кажется, что вы используете хранилище только в качестве хранилища данных и, возможно, упускаете из виду его реактивность, не позволяя ему также контролировать переменные, на которые реагирует ваше приложение. По сути, вы можете и должны выгрузить некоторые строки кода, написанные в ваших компонентах, в свои магазины.

Alex
источник