Spec-Zone.ru › Vuex 4

Мутации

Попробуйте этот урок на Scrimba

Единственный способ фактически изменить состояние в хранилище 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.

Чтобы обрабатывать асинхронные операции, давайте представим действия.

Изменить эту страницу на GitHub

Последнее обновление:

Получатели
Действия

© 2015–present Evan You
Licensed under the MIT License.
https://next.vuex.vuejs.org/guide/mutations.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API