Provide/inject.
Часть 2: Где и когда использовать?
В
прошлой части мы рассмотрели рекомендации по использованию provide/inject (давайте для краткости будем называть это контекстом, так как это наименование используется в большинстве фреймворков). И так, где же будет уместно использование контекста.
Для начала я бы рассмотрел природу этого механизма, чтобы делать какие-то выводы:
1. Оно сквозное - самый принцип который узнают все пользователи, что это способ избежать необходимости прокидывать пропсы, чтобы доносить его до низлежащих компонентов, что роднит его с глобальным стейтом, который тоже доступен ото всюду
2. Оно иерархическое - а вот это наиболее интересный и важный пункт. Это свойство позволяет от любого компонента строить иерархию контекстов на всю глубину/до переопределения. Это роднит его с пропсами, когда каждый компонент имеет свой стейт, только тут поддерево
Таким образом оно позволяет нам что-то синхронизировать на всей протяженности поддерева на котором оно определено. Где бывает такое нужно:
1. Компоненты с четкой иерархией. Например Tabs и Tab. В этом случае очевидно, что Tab без Tabs не имеет смысла и одно вложено в другое, а Tabs может отправлять необходимые данные или использование данные от Tab через контекст. Еще примеры таких компонентов: RadioGroup+Radio / Form+inputs. На самом деле современные headless ui библиотеки буквально полностью построены на таких иерархиях и иногда эти особенности называют "анатомией компонента", те какие компоненты во что могут быть вложены и из чего состоят. Поэтому если вам нужно создать компонент который работает в паре с другим компонентом, то это нормально завести для их взаимодействия контекст.
2. Работа плагинов и прочие глобальные "неявное API". Вот вы используете Pinia / Vuex / VueRouter и тд. А как вообще они узнают информацию о роутере и так далее, они на самом деле они прокидывают контекст в корень приложения и далее вам не нужно переживать как они это используют, они просто достанут из контекста всю информацию для работы API. Поэтому если вам нужно универсальное API, без глобального стора(например потому что вы пишите внутренний плагин или возможно множество инстансов), то это отличный вариант.
3. Сервисы ограниченные поддеревом. Наиболее интересная и при этом наиболее неразвитое направление в использовании. Это буквально наиболее активно используемый механизм в ангуляре, на его основе работает продвинутое DI и так далее. Что это такое? Вот обычно мы логику с данными которая может использоваться несколькими компонентами в глобальный стор, а что делать если это нужно нам лишь в определенной части приложения или нам вообще нужно множество таких инстансов запустить? Тут идут как раз трюки с добавлением id к именам сторов в Pinia и прочие трюки по "размножению" STM, а по факту раз это имеет смысл лишь в определенном поддереве приложения, то именно этот механизм наиболее аккуратно может быть взят для использования. Таким образом можно даже включать различные цветовые темы в разных подчастях приложения.
4. API важное лишь на определенных страницах. Это по факту 3ий пункт, но более специализированный. По сути это призыв не пихать все подряд в глобальный стор, на то он и глобальный, что должен иметь смысл ВЕЗДЕ. А если он несет смысл лишь на конкретных страницах, то это API этих страниц и лучшим решением будет запуска сервиса на этих страницах и прокидыванием его в контекст и взаимодействиями через него же. Таким образом можно сохранять ваш стм чистым от специфичной логики и держать специфичные сервисы ближе к месту их использования (особенно если вы используете модульную архитектуру проекта)
Таким образом мы обрисовали основные причины для использования provide/inject во Vue приложениях
#di #my #learn