State, getters, actions

State — центральное хранилище данных приложения. Он представляет собой объект, в котором содержится всё состояние, используемое компонентами. Основная идея заключается в том, что единственным источником истины для данных становится store, а не локальные состояния отдельных компонентов.

State должен быть:

  • предсказуемым — структура и начальные значения определены заранее;
  • реактивным — изменения автоматически отражаются в интерфейсе;
  • централизованным — данные доступны из любого компонента через единый механизм.

Пример объявления state:

const store = createStore({
  state() {
    return {
      count: 0,
      user: {
        id: null,
        name: ''
      },
      isAuthenticated: false
    }
  }
})

Использование функции для возврата state обязательно, так как это предотвращает утечки состояния при создании нескольких экземпляров store (актуально для SSR).

Доступ к state внутри компонентов осуществляется через объект store:

this.$store.state.count

или с использованием Composition API:

import { useStore } from 'vuex'

const store = useStore()
console.log(store.state.count)

Прямое изменение state запрещено. Это правило обеспечивает прозрачность потока данных и упрощает отладку. Все изменения должны происходить через специальные механизмы.


Getters

Getters — это вычисляемые свойства для store. Они используются для получения производных данных на основе state, аналогично computed-свойствам в компонентах.

Основные задачи getters:

  • инкапсуляция логики вычислений;
  • повторное использование вычисляемых значений;
  • упрощение структуры компонентов.

Пример getter:

const store = createStore({
  state() {
    return {
      todos: [
        { id: 1, text: 'Изучить Vue', done: true },
        { id: 2, text: 'Изучить Vuex', done: false }
      ]
    }
  },
  getters: {
    completedTodos(state) {
      return state.todos.filter(todo => todo.done)
    },
    completedCount(state, getters) {
      return getters.completedTodos.length
    }
  }
})

Getters получают:

  1. state — текущее состояние;
  2. getters — доступ к другим getters;
  3. rootState и rootGetters — при использовании модулей.

Доступ к getters:

this.$store.getters.completedCount

или:

store.getters.completedCount

Getters кэшируются на основе зависимостей. Пересчёт происходит только при изменении используемых значений state, что положительно влияет на производительность.


Actions

Actions отвечают за выполнение логики, связанной с изменением состояния. В отличие от mutations, они могут быть асинхронными и содержать побочные эффекты: HTTP-запросы, таймеры, работу с API браузера.

Основные характеристики actions:

  • не изменяют state напрямую;
  • вызывают mutations;
  • могут возвращать промисы;
  • поддерживают сложную бизнес-логику.

Пример action:

const store = createStore({
  state() {
    return {
      count: 0
    }
  },
  mutations: {
    increment(state, payload) {
      state.count += payload
    }
  },
  actions: {
    incrementAsync({ commit }, payload) {
      return new Promise(resolve => {
        setTimeout(() => {
          commit('increment', payload)
          resolve()
        }, 1000)
      })
    }
  }
})

Контекст action (context) предоставляет доступ к:

  • state
  • getters
  • commit
  • dispatch
  • rootState
  • rootGetters

Чаще всего используется деструктуризация:

actions: {
  fetchUser({ commit }) {
    // логика загрузки данных
  }
}

Вызов action из компонента:

this.$store.dispatch('incrementAsync', 5)

или с использованием async/await:

await store.dispatch('incrementAsync', 5)

Actions подходят для:

  • работы с сервером;
  • обработки ошибок;
  • последовательных или параллельных операций;
  • сложных сценариев изменения состояния.

Поток данных

Архитектура state management строится на однонаправленном потоке данных:

  1. Компонент инициирует действие (dispatch)
  2. Action выполняет логику
  3. Action вызывает mutation (commit)
  4. Mutation синхронно изменяет state
  5. Интерфейс автоматически обновляется

Такой подход обеспечивает:

  • предсказуемость изменений;
  • удобную отладку;
  • возможность логирования и тайм-тревел дебага.

Связь state, getters и actions

Эти три сущности работают как единый механизм:

  • State хранит данные
  • Getters описывают, как данные читаются
  • Actions определяют, когда и при каких условиях данные изменяются

Пример связанной логики:

state: {
  products: [],
  loading: false
},
getters: {
  availableProducts(state) {
    return state.products.filter(p => p.available)
  }
},
actions: {
  async loadProducts({ commit }) {
    commit('setLoading', true)
    const data = await api.getProducts()
    commit('setProducts', data)
    commit('setLoading', false)
  }
}

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