Что такое Vuex и как он устроен?
Vuex — это официальная библиотека управления состоянием для Vue.js (в первую очередь для Vue 2, но совместима и с Vue 3). Она предоставляет централизованное хранилище (store) для всех компонентов приложения, позволяя предсказуемо управлять состоянием, организовывать бизнес-логику и обмен данными между компонентами. Vuex реализует концепции Flux/Redux, адаптированные под реактивность Vue.
Зачем нужен Vuex
Vuex решает проблему передачи данных между компонентами в сложных приложениях. Когда дерево компонентов становится глубоким, передача данных через props и события становится сложной и запутанной. Vuex предоставляет единый источник истины, позволяя любому компоненту получать или обновлять общее состояние, не нарушая реактивности.
Структура Vuex
Vuex основан на четкой архитектуре с четырьмя основными элементами:
-
State — централизованное хранилище данных.
-
Getters — вычисляемые свойства на основе state.
-
Mutations — синхронные функции, изменяющие состояние.
-
Actions — асинхронная логика, которая вызывает mutations.
-
Modules — разбиение store на части (при большом приложении).
Пример базового Vuex store
import { createStore } from 'vuex';
const store = createStore({
state() {
return {
count: 0
};
},
getters: {
doubleCount(state) {
return state.count \* 2;
}
},
mutations: {
increment(state) {
state.count++;
},
setCount(state, payload) {
state.count = payload;
}
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
}
}
});
В Vue 2 store создавался через new Vuex.Store({ ... }), в Vue 3 — через createStore.
Использование store в компонентах
Чтение из state:
import { useStore } from 'vuex';
import { computed } from 'vue';
setup() {
const store = useStore();
const count = computed(() => store.state.count);
return { count };
}
Использование геттеров:
const double = computed(() => store.getters.doubleCount);
Вызов мутаций:
const increment = () => store.commit('increment');
Вызов экшенов:
const asyncIncrement = () => store.dispatch('asyncIncrement');
Отличия между actions и mutations
Характеристика | Mutations | Actions |
---|---|---|
Тип | Синхронные | Асинхронные возможны |
--- | --- | --- |
Изменяют state | Да | Нет (но вызывают mutations) |
--- | --- | --- |
Где используются | Прямо в компонентах | Для сетевых запросов, таймеров |
--- | --- | --- |
Пример вызова | commit('increment') | dispatch('asyncIncrement') |
--- | --- | --- |
Модули (modules)
Vuex позволяет разбивать store на модули, каждый из которых содержит собственные state, getters, mutations, actions.
const moduleA = {
namespaced: true,
state() {
return { count: 0 };
},
mutations: {
increment(state) {
state.count++;
}
}
};
const store = createStore({
modules: {
a: moduleA
}
});
Вызов:
store.commit('a/increment');
Модули могут быть вложенными и динамически регистрируемыми (например, при загрузке страницы).
namespaced: true
По умолчанию все модули используют глобальные имена мутаций и геттеров. При namespaced: true все обращения происходят с префиксом:
store.dispatch('a/asyncIncrement');
store.getters\['a/doubleCount'\];
Реактивность и ограничения
Vuex использует реактивность Vue под капотом. Поэтому при обновлении state, все компоненты, подписанные на это состояние (через computed()), автоматически перерисуются.
Ограничения:
-
нельзя напрямую менять state (например: store.state.count++ вне мутаций);
-
мутации должны быть синхронными — иначе состояние теряет предсказуемость;
-
экшены не могут напрямую менять state, только через мутации.
Интеграция с devtools
Vuex хорошо интегрируется с Vue Devtools:
-
можно отслеживать каждый commit, dispatch, payload, старое и новое состояние;
-
поддерживает time-travel debugging (перемотка состояний);
-
можно экспортировать и импортировать состояния.
Динамическая регистрация модулей
Vuex позволяет добавлять модули во время выполнения, например:
store.registerModule('user', {
state: { name: 'admin' }
});
Удаление:
store.unregisterModule('user');
Это удобно при ленивой загрузке маршрутов или функциональности.
Ограничения и замены Vuex
Vuex был популярен в эпоху Vue 2, но с появлением Composition API многие приложения переходят на Pinia — более лёгкую и современную альтернативу, также официально поддерживаемую Vue-командой. Pinia предоставляет тот же функционал, но с более простой архитектурой, типизацией и лучшей интеграцией с Vue 3.