Для чего нужен provide/inject во Vue
Что проверяют
Понимаете ли вы, какую проблему решает механизм (проброс пропсов через много уровней) и чем он отличается от глобального стора. Почти всегда следом спрашивают, реактивно ли значение из inject и как это правильно сделать во Vue 3.
Как отвечать
Предок объявляет значение через provide, любой потомок на любой глубине получает его через inject, промежуточные компоненты о нём не знают. Это внедрение зависимостей по дереву компонентов, а не глобальное состояние: разные поддеревья могут получить разные значения.
Во Vue 3 с Composition API:
provide(key, value): вызывается вsetupили<script setup>. Ключом лучше делатьSymbol, типизированный черезInjectionKey<T>: так нет коллизий строк и есть типы в TypeScript;inject(key, defaultValue): второй аргумент задаёт значение по умолчанию. Без него и без провайдера придётundefinedи предупреждение в консоли;- реактивность: если передать
refилиreactive, потомки видят изменения, обычное значение реактивным не станет. В Options APIprovide()отдаёт значение на момент вызова, заменуthis.userпотомки не увидят, поэтому оборачивают вcomputed(() => this.user); - изменения: хороший тон менять состояние только у провайдера, потомкам отдают
readonly(state)и отдельную функцию для изменения; app.provide: значение для всего приложения, так Vue Router и Pinia отдают свои объекты компонентам.
Где уместно: составные компоненты (Tabs и Tab, Form и FormItem), тема, локаль, конфиг UI-библиотеки. Общее состояние, которое меняют из разных мест, лучше держать в Pinia: там есть devtools и понятная точка изменений.
Где спотыкаются
Утверждают, что provide/inject нереактивен вообще. Он не делает значение реактивным сам, но исправно передаёт ref и reactive.
Советуют Vuex. Для новых проектов на Vue 3 официальный стор это Pinia, Vuex находится в режиме поддержки.
Строят на inject всё приложение. Компонент начинает зависеть от невидимого предка, его сложно переиспользовать и тестировать без обёртки с провайдером.