Мутации
Единственный способ фактически изменить состояние в хранилище Vuex — это совершить мутацию. Мутации Vuex очень похожи на события: каждая мутация имеет строковый тип и обработчик. Функция-обработчик — это место, где мы выполняем фактические изменения состояния, и она будет получать состояние в качестве первого аргумента:
const store = createStore({
state: {
count: 1
},
mutations: {
increment (state) {
// mutate state
state.count++
}
}
})
Вы не можете напрямую вызвать обработчик мутации. Представьте это скорее как регистрацию события: «Когда триггерится мутация с типом increment , вызывайте этот обработчик». Чтобы вызвать обработчик мутации, вам нужно вызвать store.commit с его типом:
store.commit('increment')
Совершение мутации с полезной нагрузкой
Вы можете передать дополнительный аргумент в store.commit, который называется полезной нагрузкой для мутации:
// ...
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
В большинстве случаев полезная нагрузка должна быть объектом, чтобы она могла содержать несколько полей, и записанная мутация также будет более описательной:
// ...
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
store.commit('increment', {
amount: 10
})
Совершение мутации в стиле объекта
Альтернативный способ совершения мутации — это прямое использование объекта, имеющего свойство type:
store.commit({
type: 'increment',
amount: 10
})
При использовании совершения мутации в стиле объекта весь объект будет передан в качестве полезной нагрузки обработчикам мутаций, поэтому обработчик остается тем же:
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
Использование констант для типов мутаций
В различных реализациях Flux часто используется шаблон использования констант для типов мутаций. Это позволяет коду использовать инструменты, такие как линтеры, а размещение всех констант в одном файле позволяет вашим коллегам быстро получить представление о возможных мутациях во всей приложении:
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import { createStore } from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = createStore({
state: { ... },
mutations: {
// we can use the ES2015 computed property name feature
// to use a constant as the function name
[SOME_MUTATION] (state) {
// mutate state
}
}
})
Использование констант — это в основном вопрос предпочтений. Это может быть полезно в больших проектах с множеством разработчиков, но это совершенно необязательно, если вам они не нравятся.
Мутации должны быть синхронными
Важно помнить, что функции-обработчики мутаций должны быть синхронными. Почему? Рассмотрим следующий пример:
mutations: {
someMutation (state) {
api.callAsyncMethod(() => {
state.count++
})
}
}
Теперь представьте, что мы отлаживаем приложение и смотрим журналы мутаций в инструменте разработки. Для каждой записанной мутации инструмент разработки должен захватить «до» и «после» состояния. Однако асинхронный обратный вызов внутри примера мутации выше делает это невозможным: обратный вызов ещё не вызван, когда мутация совершается, и инструмент разработки не может знать, когда обратный вызов будет фактически вызван — любое изменение состояния, выполненное в обратном вызове, по существу не отслеживается!
Совершение мутаций в компонентах
Вы можете совершать мутации в компонентах с помощью this.$store.commit('xxx'), или использовать вспомогательную функцию mapMutations, которая сопоставляет методы компонента с вызовами store.commit (требуется инъекция корневого store):
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // map `this.increment()` to `this.$store.commit('increment')`
// `mapMutations` also supports payloads:
'incrementBy' // map `this.incrementBy(amount)` to `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // map `this.add()` to `this.$store.commit('increment')`
})
}
}
Переходим к действиям
Асинхронность в сочетании с мутациями состояния может значительно затруднить понимание вашего приложения. Например, когда вы вызываете два метода, оба с асинхронными обратными вызовами, изменяющими состояние, как вы узнаете, когда они вызваны и какой обратный вызов был вызван первым? Именно поэтому мы хотим разделить эти два понятия. В Vuex мутации — это синхронные транзакции:
store.commit('increment')
// any state change that the "increment" mutation may cause
// should be done at this moment.
Чтобы обрабатывать асинхронные операции, давайте представим действия.
© 2015–present Evan You
Licensed under the MIT License.
https://next.vuex.vuejs.org/guide/mutations.html