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

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

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

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

65 голосов | спросил Kobi 2 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 02 Sep 2016 21:53:22 +0300 2016, 21:53:22

9 ответов


0

Вопрос 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)
}

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

  • мутация - это единственный способ изменить состояние
  • мутация не заботится о бизнес-логике, она просто заботится о «состоянии»
  • действие - это бизнес-логика
  • action может отправлять более 1 мутации за раз, он просто реализует бизнес-логику, ему не важно изменение данных (которое управляется мутацией)
ответил Kaicui 3 rdEurope/Moscowp30Europe/Moscow09bEurope/MoscowSat, 03 Sep 2016 08:55:11 +0300 2016, 08:55:11
0

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

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

ответил Bas 15 22016vEurope/Moscow11bEurope/MoscowTue, 15 Nov 2016 16:02:06 +0300 2016, 16:02:06
0

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

ответил Noah Namey 25 MaramSat, 25 Mar 2017 05:17:46 +03002017-03-25T05:17:46+03:0005 2017, 05:17:46
0

Согласно 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

ответил Abdullah Khan 13 WedEurope/Moscow2017-12-13T12:52:34+03:00Europe/Moscow12bEurope/MoscowWed, 13 Dec 2017 12:52:34 +0300 2017, 12:52:34
0

Отказ от ответственности - я только начал использовать 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 19 MonEurope/Moscow2016-12-19T05:23:39+03:00Europe/Moscow12bEurope/MoscowMon, 19 Dec 2016 05:23:39 +0300 2016, 05:23:39
0

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

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

  

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

Строго говоря, вы можете изменить 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 и плагины знают об изменениях в результате мутаций, мы должны продолжать использовать их в своих действиях. Это обеспечивает уровень согласованности.

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

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

  

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

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

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

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

Вышесказанное кажется мне немного запутанным. Я воспринял это как указание на то, что ряд решений в дизайне Vuex, вероятно, были приняты при обеспечении возможности размещения vue-devtools.

ответил Michael Ekoka 30 +03002018-10-30T01:25:03+03:00312018bEurope/MoscowTue, 30 Oct 2018 01:25:03 +0300 2018, 01:25:03
0

Мутации:

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

Почему оба ??

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

ответил Gopinath Kaliappan 17 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 17 Sep 2018 11:41:39 +0300 2018, 11:41:39
0

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

  

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

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

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

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

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

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

ответил aircraft 18 PMpWed, 18 Apr 2018 12:06:25 +030006Wednesday 2018, 12:06:25
0

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

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

ответил Sumit Patel 11 J0000006Europe/Moscow 2018, 12:10:28

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132