Vue 3 предлагает гибкие инструменты для обмена данными между компонентами.
Если props и emits позволяют взаимодействовать между родителем и ребёнком, то provide и inject дают возможность передавать данные через несколько уровней вложенности, а Pinia обеспечивает централизованное и удобное хранение состояния во всём приложении.
🧩 1. Что такое provide и inject
В больших приложениях данные часто нужно передавать вглубь дерева компонентов, минуя промежуточные уровни.
Чтобы не прокидывать props вручную через каждый уровень, Vue 3 предлагает механизм provide и inject.
provide— «предоставляет» значение.inject— «получает» это значение в любом дочернем компоненте.
Пример:
<!-- App.vue -->
<template>
<h1>Главный компонент</h1>
<ChildComponent />
</template>
<script setup>
import { ref, provide } from 'vue'
import ChildComponent from './ChildComponent.vue'
const theme = ref('dark')
provide('theme', theme)
</script>
<!-- ChildComponent.vue -->
<template>
<p>Текущая тема: {{ theme }}</p>
</template>
<script setup>
import { inject } from 'vue'
const theme = inject('theme')
</script>
Теперь компонент ChildComponent имеет доступ к значению theme, даже если между ним и App.vue есть другие уровни вложенности.
⚙️ 2. Реактивность с provide/inject
Если ты передаёшь реактивные значения (ref или reactive), то изменения автоматически обновятся во всех компонентах, которые их используют.
<!-- App.vue -->
<template>
<button @click="toggleTheme">Переключить тему</button>
<ChildComponent />
</template>
<script setup>
import { ref, provide } from 'vue'
import ChildComponent from './ChildComponent.vue'
const theme = ref('dark')
function toggleTheme() {
theme.value = theme.value === 'dark' ? 'light' : 'dark'
}
provide('theme', theme)
</script>
Теперь при изменении theme интерфейс всех дочерних компонентов обновится автоматически.
Это и есть сила реактивности Vue 3.
🧠 3. Когда использовать provide/inject
✅ Подходит для:
тем оформления (dark/light);
локализации (i18n);
настроек форм;
зависимостей и сервисов (например, конфиг API).
⚠️ Не подходит для:
хранения общего состояния приложения (например, корзина, пользователь, настройки профиля).
В таких случаях лучше использовать Pinia — современный менеджер состояния.
🧬 4. Pinia — современный state manager для Vue 3
Pinia — это официальная библиотека управления состоянием для Vue 3, пришедшая на смену Vuex.
Она проста, основана на Composition API и поддерживает TypeScript «из коробки».
Pinia позволяет хранить данные централизованно и использовать их в любых компонентах без цепочек props и emit.
⚙️ 5. Установка и настройка Pinia
Установим Pinia:
npm install pinia
Подключим её в main.js:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
🧩 6. Создание хранилища (store)
Хранилище — это как мини-база данных твоего приложения.
// stores/useCounterStore.js
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
// состояние
const count = ref(0)
// геттер (computed)
const double = computed(() => count.value * 2)
// действия
function increment() {
count.value++
}
// возвращаем всё, что хотим использовать снаружи
return { count, double, increment }
})
💻 7. Использование Pinia в компоненте
<template>
<h2>Счётчик: {{ counter.count }}</h2>
<p>Удвоенное значение: {{ counter.double }}</p>
<button @click="counter.increment">+</button>
</template>
<script setup>
import { useCounterStore } from '@/stores/useCounterStore'
const counter = useCounterStore()
</script>
Хранилище counter теперь доступно во всём приложении.
Можно вызывать методы, изменять состояние и использовать геттеры — всё реактивно и удобно.
💡 Заключение
provide и inject — отличное решение для локального обмена данными между компонентами.
Pinia — мощный инструмент для глобального управления состоянием во Vue 3.
Используя их вместе, ты можешь строить гибкие, масштабируемые и легко поддерживаемые приложения.
Vue3.ru