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

Как передать информацию об изменениях одного компонента другому через VUIX?

2.0 Middle🔥 201 комментариев
#Vue.js

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Передача данных об изменениях между компонентами

Вопрос относится к передаче реактивных данных между несвязанными компонентами (не parent-child). Есть несколько подходов в зависимости от того, как организована архитектура приложения.

Основные способы передачи информации

1. Event Bus / Mitt Паттерн для общения независимых компонентов через события.

2. Pinia / Vuex Централизованное хранилище состояния приложения.

3. Provide/Inject Передача данных через иерархию компонентов (работает и для несвязанных).

4. Reactive/Ref с экспортом Использование Vue 3 Composition API с внешним состоянием.

5. localStorage / sessionStorage Для синхронизации между вкладками и сеансами.

Примеры кода

// СПОСОБ 1: Event Bus (mitt)
// eventBus.js
import { createApp } from 'vue';
import mitt from 'mitt';

const emitter = mitt();
export default emitter;

// ComponentA.vue (отправитель)
import emitter from './eventBus';

export default {
  methods: {
    notifyChange() {
      emitter.emit('dataChanged', {
        id: 1,
        name: 'John',
        status: 'active'
      });
    }
  }
}

// ComponentB.vue (получатель)
import { onMounted, onUnmounted } from 'vue';
import emitter from './eventBus';

export default {
  setup() {
    const handleDataChange = (data) => {
      console.log('Получены изменения:', data);
    };
    
    onMounted(() => {
      emitter.on('dataChanged', handleDataChange);
    });
    
    onUnmounted(() => {
      emitter.off('dataChanged', handleDataChange);
    });
    
    return {};
  }
}

СПОСОБ 2: Pinia (современный подход)

// store.js
import { defineStore } from 'pinia';
import { ref } from 'vue';

export const useUserStore = defineStore('user', () => {
  const user = ref(null);
  const lastUpdate = ref(null);
  
  const setUser = (newUser) => {
    user.value = newUser;
    lastUpdate.value = new Date();
    console.log('User updated:', newUser);
  };
  
  const updateField = (field, value) => {
    if (user.value) {
      user.value[field] = value;
      lastUpdate.value = new Date();
    }
  };
  
  return { user, lastUpdate, setUser, updateField };
});

// ComponentA.vue (отправитель)
import { useUserStore } from './store';

export default {
  setup() {
    const userStore = useUserStore();
    
    const handleChange = (newUser) => {
      userStore.setUser(newUser);
    };
    
    return { handleChange };
  }
}

// ComponentB.vue (получатель)
import { useUserStore } from './store';

export default {
  setup() {
    const userStore = useUserStore();
    
    return {
      user: userStore.user,
      lastUpdate: userStore.lastUpdate
    };
  }
}

СПОСОБ 3: Provide/Inject

// App.vue
import { ref, provide } from 'vue';

export default {
  setup() {
    const sharedData = ref({
      user: null,
      lastModified: null
    });
    
    const updateSharedData = (newData) => {
      sharedData.value = newData;
    };
    
    provide('sharedData', {
      data: sharedData,
      updateSharedData
    });
  }
}

// ComponentA.vue (отправитель)
import { inject } from 'vue';

export default {
  setup() {
    const { updateSharedData } = inject('sharedData');
    
    const notifyChange = (newData) => {
      updateSharedData(newData);
    };
    
    return { notifyChange };
  }
}

// ComponentB.vue (получатель)
import { inject } from 'vue';

export default {
  setup() {
    const { data } = inject('sharedData');
    return { sharedData: data };
  }
}

СПОСОБ 4: Composition API с экспортируемым состоянием

// composables/useSharedData.js
import { ref, watch } from 'vue';

const sharedState = ref({
  user: null,
  lastUpdate: null,
  version: 0
});

export function useSharedData() {
  const updateData = (newData) => {
    sharedState.value = {
      ...newData,
      version: sharedState.value.version + 1,
      lastUpdate: new Date()
    };
  };
  
  const onDataChange = (callback) => {
    watch(() => sharedState.value, callback, { deep: true });
  };
  
  return {
    sharedState,
    updateData,
    onDataChange
  };
}

// ComponentA.vue
import { useSharedData } from './composables/useSharedData';

export default {
  setup() {
    const { updateData } = useSharedData();
    
    const handleChange = (newUser) => {
      updateData({ user: newUser });
    };
    
    return { handleChange };
  }
}

// ComponentB.vue
import { useSharedData } from './composables/useSharedData';

export default {
  setup() {
    const { sharedState, onDataChange } = useSharedData();
    
    onDataChange((newState) => {
      console.log('Data changed:', newState);
    });
    
    return { sharedState };
  }
}

СПОСОБ 5: localStorage для синхронизации

// composables/useSyncedState.js
import { ref, watch } from 'vue';

export function useSyncedState(key, initialValue) {
  const data = ref(
    localStorage.getItem(key) 
      ? JSON.parse(localStorage.getItem(key)) 
      : initialValue
  );
  
  watch(data, (newValue) => {
    localStorage.setItem(key, JSON.stringify(newValue));
    window.dispatchEvent(new CustomEvent('storageSync', {
      detail: { key, value: newValue }
    }));
  }, { deep: true });
  
  const handleStorageChange = (event) => {
    if (event.key === key) {
      data.value = event.newValue 
        ? JSON.parse(event.newValue) 
        : initialValue;
    }
  };
  
  window.addEventListener('storage', handleStorageChange);
  
  return { data };
}

Сравнение подходов

Event Bus - простой, но низкая масштабируемость Pinia - средняя сложность, высокая масштабируемость Provide/Inject - средняя сложность, для иерархии Composition API - высокая масштабируемость localStorage - для синхронизации между вкладками

Рекомендация

Для небольших приложений: используй Event Bus или Provide/Inject. Для приложений среднего размера: используй Pinia и Composition API. Для синхронизации между вкладками: localStorage + Custom Events.

Заключение

В Vue 3 лучший способ передать информацию об изменениях между несвязанными компонентами — использовать Pinia (хранилище состояния) или Composition API с provide/inject. Это обеспечивает реактивность, масштабируемость и чистоту кода.