← Назад к вопросам
В чем разница между Vuex и глобальной переменной?
2.0 Middle🔥 151 комментариев
#Vue.js
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между Vuex и глобальной переменной
Что такое Vuex
Vuex — это библиотека управления состоянием для Vue.js приложений. Это часть официального экосистема Vue и предоставляет централизованное хранилище (store) для состояния, которое используется во всём приложении.
В современных проектах часто используют Pinia (официальная замена Vuex 5+), но концепции одинаковые.
Что такое глобальная переменная
Глобальная переменная — это переменная, объявленная в глобальной области видимости, доступная из любого места в коде:
// Глобальная переменная
window.globalState = { user: null, count: 0 };
// Или просто без window
var globalState = { user: null, count: 0 };
// Доступна отовсюду
console.log(globalState.user);
globalState.count++;
Сравнение: Vuex vs Глобальная переменная
// =========== ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ ===========
// Определение
window.appState = {
user: null,
items: [],
isLoading: false
};
// Использование в компоненте
export default {
data() {
return {
state: window.appState // Копируем ссылку
};
},
template: `
<div>
<p>{{ state.user?.name }}</p>
<button @click="state.count++">Increment</button>
</div>
`
};
// =========== VUEX ===========
// store.js
import { createStore } from 'vuex';
export default createStore({
state() {
return {
user: null,
items: [],
isLoading: false
};
},
mutations: {
setUser(state, user) {
state.user = user;
},
setLoading(state, value) {
state.isLoading = value;
}
},
actions: {
async fetchUser({ commit }, userId) {
commit('setLoading', true);
const user = await api.getUser(userId);
commit('setUser', user);
commit('setLoading', false);
}
},
getters: {
userName(state) {
return state.user?.name || 'Anonymous';
},
isAuthenticated(state) {
return state.user !== null;
}
}
});
// Использование в компоненте
export default {
template: `
<div>
<p>{{ $store.getters.userName }}</p>
<button @click="incrementCount">Increment</button>
</div>
`,
methods: {
incrementCount() {
this.$store.commit('setUser', { name: 'John' });
// или
this.$store.dispatch('fetchUser', 123);
}
}
};
Основные отличия
1. Предсказуемость и отладка
// ❌ ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ
// Состояние может изменяться ОТКУДА УГОДНО и КОГДА УГОДНО
window.appState = { count: 0 };
function random() {
window.appState.count++; // Где это произойдёт? Когда? Почему?
}
function another() {
window.appState.count = -99; // Или тут?
}
// В большом приложении невозможно отследить, кто меняет состояние
// ✅ VUEX
// Состояние меняется ТОЛЬКО через mutations
mutations: {
incrementCount(state) {
state.count++;
}
}
// Все изменения в одном месте, легко отследить и отладить
2. Time-Travel Debugging
// ✅ Vuex DevTools (специальное расширение Chrome)
// Можно:
// - Видеть ВСЕ действия в хронологическом порядке
// - Откатиться на предыдущее состояние
// - Перепроиграть действия
// - Отправить старое состояние
// ❌ Глобальная переменная
// Таких инструментов нет
// Максимум console.log(window.appState)
3. Реактивность и перерендеры
// ❌ ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ
window.appState = { user: null };
// Компонент НЕ автоматически переренденируется
export default {
data() {
return { state: window.appState };
},
template: `<p>{{ state.user?.name }}</p>` // НЕ обновится!
};
// Нужно вручную вызвать update
window.appState.user = { name: "John" };
// Компонент НЕ знает об этом изменении!
// ✅ VUEX
// Vue отслеживает изменения state через mutations
mutations: {
setUser(state, user) {
state.user = user; // Vue автоматически обновит UI
}
}
// Компонент переренденируется автоматически
export default {
template: `<p>{{ $store.state.user?.name }}</p>` // Обновится!
};
4. Тестирование
// ❌ ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ
// Тесты загрязняют друг друга
test('test 1', () => {
window.appState.count = 10;
expect(window.appState.count).toBe(10);
});
test('test 2', () => {
// count ещё 10 с предыдущего теста!
console.log(window.appState.count); // 10, а не 0
window.appState.count++;
});
// Нужно вручную очищать после каждого теста
afterEach(() => {
window.appState = { count: 0 }; // Очистка
});
// ✅ VUEX / PINIA
// Легко мокировать и изолировать
test('test 1', () => {
const store = createStore({ /* ... */ });
store.commit('increment');
expect(store.state.count).toBe(1);
});
test('test 2', () => {
const store = createStore({ /* ... */ }); // Новый store для каждого теста
expect(store.state.count).toBe(0);
});
// Каждый тест получает чистый store
5. Масштабируемость
// ❌ ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ
window.appState = {
user: { name: "", email: "", role: "" },
items: [],
filters: { status: "", sort: "" },
ui: { isMenuOpen: false, theme: "light" },
cache: { users: {}, items: {} },
// ... 50+ свойств
};
// Состояние растёт, становится запутанным
// Непонятно, какие свойства используются где
// Сложно добавлять новые возможности
// ✅ VUEX
// Состояние организовано по модулям
const store = createStore({
modules: {
user: userModule, // Всё про пользователей
items: itemsModule, // Всё про товары
ui: uiModule, // Всё про UI
cache: cacheModule // Всё про кэш
}
});
// Каждый модуль имеет свой state, mutations, actions, getters
// Легко навигировать и расширять
6. DevX (Developer Experience)
// ❌ ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ
window.appState.user = { name: "John" };
// Нет автодополнения в IDE
// Нет подсказок типов
// Легко сделать опечатку
window.appState.userName = "John"; // Опечатка! Работает, но неправильно
// ✅ VUEX (с TypeScript)
interface State {
user: { name: string };
}
const store = createStore<State>({
state: () => ({ user: { name: "" } }),
mutations: {
setUser(state, user: { name: string }) {
state.user = user;
}
}
});
// IDE подскажет типы
// Будет ошибка при опечатке
store.commit('setUser', { name: 'John' }); // ✓
store.commit('setUserName', { name: 'John' }); // ✗ TypeError
Практический пример: Счётчик
// ❌ ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ
window.count = 0;
// Components.vue
export default {
methods: {
increment() {
window.count++;
// UI не обновится автоматически!
this.$forceUpdate(); // Нужно вручную
}
},
template: `
<div>
<p>Count: {{ window.count }}</p>
<button @click="increment">+</button>
</div>
`
};
// ✅ VUEX
// store.js
export default createStore({
state: () => ({ count: 0 }),
mutations: {
increment(state) {
state.count++;
}
}
});
// Component.vue
export default {
methods: {
increment() {
this.$store.commit('increment'); // Просто!
}
},
template: `
<div>
<p>Count: {{ $store.state.count }}</p>
<button @click="increment">+</button>
</div>
`
};
// UI обновится автоматически
Когда использовать что
// ✅ ГЛОБАЛЬНАЯ ПЕРЕМЕННАЯ
// - Очень небольшое приложение (только для быстрого прототипирования)
// - Одиночное значение, которое редко меняется
// - (РЕДКО! Не используй для production)
// ✅ VUEX / PINIA
// - Приложение средне-крупного размера
// - Общее состояние, используемое в разных компонентах
// - Нужна отладка и Time-Travel
// - Нужна типизация и предсказуемость
// ✅ ПРОСТОЕ СОСТОЯНИЕ (Vue 3 Composition API)
// - Небольшие приложения
// - Состояние, используемое в нескольких компонентах
// - Не нужны сложные инструменты
import { reactive, readonly } from 'vue';
const state = reactive({ count: 0 });
export const store = readonly(state);
export const increment = () => state.count++;
Итог
Vuex — это правильный выбор для управления состоянием в Vue приложениях:
- Предсказуемость — состояние меняется только через mutations
- Отладка — DevTools позволяет отслеживать ВСЕ изменения
- Реактивность — Vue автоматически обновляет UI
- Тестируемость — легко мокировать и изолировать
- Масштабируемость — модули и организованная структура
- DevX — типизация, автодополнение, подсказки
Глобальные переменные — это антипаттерн:
- Состояние может меняться откуда угодно
- UI не обновляется автоматически
- Сложно отладить
- Тесты загрязняют друг друга
- Не масштабируется
В современных Vue 3 приложениях используй Pinia вместо Vuex 4 — это официальная замена с лучшим DX.