← Назад к вопросам

В чем разница между 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 приложениях:

  1. Предсказуемость — состояние меняется только через mutations
  2. Отладка — DevTools позволяет отслеживать ВСЕ изменения
  3. Реактивность — Vue автоматически обновляет UI
  4. Тестируемость — легко мокировать и изолировать
  5. Масштабируемость — модули и организованная структура
  6. DevX — типизация, автодополнение, подсказки

Глобальные переменные — это антипаттерн:

  • Состояние может меняться откуда угодно
  • UI не обновляется автоматически
  • Сложно отладить
  • Тесты загрязняют друг друга
  • Не масштабируется

В современных Vue 3 приложениях используй Pinia вместо Vuex 4 — это официальная замена с лучшим DX.