Spec-Zone.ru › Vuex 3

Мутации

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

Единственный способ фактически изменить состояние в хранилище Vuex — это выполнить мутацию. Мутации Vuex очень похожи на события: каждая мутация имеет строковый **тип** и **обработчик**. Функция обработчика — это место, где мы выполняем фактические изменения состояния, и она будет получать состояние в качестве первого аргумента:

const store = new Vuex.Store({
  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
  }
}

Мутации следуют правилам реактивности Vue

Поскольку состояние хранилища Vuex делается реактивным с помощью Vue, при мутации состояния компоненты Vue, наблюдающие за состоянием, будут автоматически обновляться. Это также означает, что мутации Vuex подчиняются тем же ограничениям реактивности, что и обычные Vue:

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

  2. При добавлении новых свойств к объекту вы должны либо:

  • Использовать Vue.set(obj, 'newProp', 123), или

  • Заменить этот объект новым. Например, используя синтаксис разброса объектов, мы можем написать его так:

    state.obj = { ...state.obj, newProp: 123 }
    

Использование констант для типов мутаций

В различных реализациях Flux часто встречается практика использования констант для типов мутаций. Это позволяет коду использовать такие инструменты, как анализаторы кода, а размещение всех констант в одном файле позволяет вашим коллегам быстро ознакомиться с возможными мутациями во всём приложении:

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  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++
    })
  }
}

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

Выполнение мутаций в компонентах

Вы можете выполнить мутации в компонентах с помощью 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://vuex.vuejs.org/guide/mutations.html

Spec-Zone.ru

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