Vuex

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

Структура хранилища

Хранилище Vuex состоит из нескольких ключевых компонентов:

  • State – объект, содержащий состояние приложения.
  • Getters – функции, которые возвращают вычисляемые значения на основе состояния.
  • Mutations – синхронные функции, которые изменяют состояние.
  • Actions – асинхронные функции, вызывающие мутации.
  • Modules – способ разделить хранилище на логические части для масштабируемых приложений.

Пример базового хранилища:

import { createStore } from 'vuex';

const store = createStore({
  state: {
    count: 0
  },
  getters: {
    doubleCount: (state) => state.count * 2
  },
  mutations: {
    increment(state) {
      state.count++;
    },
    decrement(state) {
      state.count--;
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    }
  }
});

export default store;

State и реактивность

Состояние Vuex полностью реактивно. Любое изменение через мутацию автоматически обновляет все компоненты, которые используют это состояние. Рекомендуется не изменять состояние напрямую вне мутаций, чтобы сохранить предсказуемость данных.

// Неправильно:
store.state.count = 5;

// Правильно:
store.commit('increment');

Getters

Getters позволяют получать вычисляемые данные из состояния, аналогично computed в компонентах Vue. Их можно комбинировать и использовать как параметры.

getters: {
  isEven: (state) => state.count % 2 === 0
}

Использование в компоненте:

computed: {
  isEven() {
    return this.$store.getters.isEven;
  }
}

Mutations и commit

Мутации — это единственный способ изменить состояние. Они всегда синхронные и принимают state как первый аргумент и payload (данные) как второй.

mutations: {
  setCount(state, payload) {
    state.count = payload;
  }
}

// Вызов:
store.commit('setCount', 10);

Actions и dispatch

Actions используются для выполнения асинхронных операций и вызывают мутации через commit.

actions: {
  fetchData({ commit }) {
    fetch('/api/data')
      .then(res => res.json())
      .then(data => commit('setData', data));
  }
}

// Вызов:
store.dispatch('fetchData');

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

Модули

Для крупных приложений хранилище можно разбить на модули, каждый из которых имеет собственный state, getters, mutations и actions.

const userModule = {
  state: () => ({ name: 'John' }),
  mutations: {
    setName(state, payload) {
      state.name = payload;
    }
  },
  actions: {
    updateName({ commit }, name) {
      commit('setName', name);
    }
  },
  getters: {
    upperName: (state) => state.name.toUpperCase()
  }
};

const store = createStore({
  modules: {
    user: userModule
  }
});

Доступ к модулю осуществляется через путь:

this.$store.state.user.name
this.$store.getters['user/upperName']
this.$store.commit('user/setName', 'Alice')
this.$store.dispatch('user/updateName', 'Alice')

Стратегии организации хранилища

  • Flat store: один объект состояния, подходит для небольших приложений.
  • Модули: для больших проектов разделяют логику на функциональные блоки.
  • Namespaced modules: позволяют избежать конфликтов имен и делают код более читаемым.

Интеграция с Vue-компонентами

Состояние Vuex легко подключается к компонентам Vue через:

  • this.$store.state – доступ к состоянию.
  • this.$store.getters – доступ к геттерам.
  • this.$store.commit – вызов мутаций.
  • this.$store.dispatch – вызов actions.

Для более удобного использования часто применяются mapState, mapGetters, mapMutations и mapActions из Vuex:

import { mapState, mapMutations } from 'vuex';

export default {
  computed: {
    ...mapState(['count']),
  },
  methods: {
    ...mapMutations(['increment']),
  }
}

Слежение за состоянием (Devtools)

Vuex интегрируется с Vue Devtools, позволяя отслеживать изменения состояния, время вызова мутаций и actions. Это особенно важно для отладки сложных приложений и понимания потоков данных.

Практические рекомендации

  • Использовать actions для асинхронных операций, mutations только для синхронных изменений.
  • Разделять хранилище на модули для крупных проектов.
  • Не изменять state напрямую, обходясь commit.
  • Использовать getters для вычисляемых значений, чтобы избежать дублирования логики в компонентах.

Vuex формирует чёткую архитектуру управления состоянием, делает код предсказуемым и упрощает масштабирование приложений на Vue.js.