Поговорим о Shared composables
Страшный термин, который многие понимают, как хотят.
Во
1. Composable
Это технически (
2. "Модульный реф" / Pinia store
Тоже можно считать объектом в смысле
3. Shared composable как в примерах в документации во VueUse и Vue
Рождается как
Некоторые разработчики (не будем показывать пальцем) уверены, что использование
Не обладая знаниями Мурыча, тем не менее давайте намного порассуждаем.
Вот у нас есть модульный реф с рефом. Вот он используется, потом все компоненты со ссылкой на него, уничтожаются. Что происходит? Ничего. У него нет внешних зависимостей, он просто лежит мертвым грузом в памяти, занимая свои несчастные пару килобайт. Появился использующий его компонент - он заработал.
Как с
Так для чего нужен shared composable?
Посмотрим на примеры в документациях. Мы создаем реф с отслеживанием движения мышки. А вот это уже важно - если мы в каждом требующем координаты мышки компоненте будем создавать
Таким образом,
состояние в shared composable выполняет не самостоятельную функцию, а является просто адаптером для некого внешнего сервиса / Web API.
И суть
Даже чисто логически если подумать (по описанному выше юз-кейсу в пункте 3), то
Но, опять же, если подумать, то данная логика (оптимизация работы с внешним сервисом) очень похожа на логику работы глобального лоадера. И реализована может быть так же в несколько строк, безо всяких
#composable #reactivity
Страшный термин, который многие понимают, как хотят.
Во
Vue 3
у компонента есть, по большому счету, три варианта работы с внешними реактивными данными1. Composable
Это технически (
JS closure
) и по факту (ООП
) объект с данными и поведением. Компонент его создает, пользуется, при уничтожении компонента обнуляется ссылка на объект, и он подлежит уборке Garbage Collector
-ом (GC
).2. "Модульный реф" / Pinia store
Тоже можно считать объектом в смысле
ООП
, но реализующим паттерн Singleton
. Создается при первом вызове его кем-либо, затем ссылка на него записывается в некий глобальный реестр, и любой другой компонент, обращающийся к этой структуре, получает эту ссылку и работает с тем же самым инстансом.3. Shared composable как в примерах в документации во VueUse и Vue
Рождается как
стор
, умирает как обычный composable
. При первом обращении создается один объект, который затем используется всеми компонентами, которым он нужен. Но как только не остается ни одного такого компонента, этот объект "умирает". В дальнейшем если он понадобится, он создается опять в одном экземпляре.Некоторые разработчики (не будем показывать пальцем) уверены, что использование
shared composable
именно как реактивного стейта вместо модульного рефа/стора помогает сделать программу эффективней.Не обладая знаниями Мурыча, тем не менее давайте намного порассуждаем.
Вот у нас есть модульный реф с рефом. Вот он используется, потом все компоненты со ссылкой на него, уничтожаются. Что происходит? Ничего. У него нет внешних зависимостей, он просто лежит мертвым грузом в памяти, занимая свои несчастные пару килобайт. Появился использующий его компонент - он заработал.
Как с
shared composable
? Вот он создается, используется, потом все компоненты, его использующие, кончаются - и он должен типа уничтожиться. Вызывается код по обнулению, но у Garbage Collector
-а JS VM
своя логика работы, и он не будет чистить эту память сразу. А если и будет - потратит на это ресурсы CPU
. Затем снова появляется компонент, которому нужен этот объект - и он снова создается, тратятся ресурсы CPU
, выделяется новая память. И так по кругу. В итоге, через 10 циклов у нас в куче памяти в 10 раз больше, чем нам надо, зарезервированного места, и мы потратили в десять раз больше ресурсов на создание/уничтожение структуры.Так для чего нужен shared composable?
Посмотрим на примеры в документациях. Мы создаем реф с отслеживанием движения мышки. А вот это уже важно - если мы в каждом требующем координаты мышки компоненте будем создавать
composable
с этой логикой, мы будем множить слушателей этого события, и это дорогая операция. Держать слушателя постоянно в глобальном сторе - тоже ненужная трата ресурсов.Таким образом,
состояние в shared composable выполняет не самостоятельную функцию, а является просто адаптером для некого внешнего сервиса / Web API.
И суть
shared composable
- создать единую реактивную точку доступа к внешнему сервису.Даже чисто логически если подумать (по описанному выше юз-кейсу в пункте 3), то
shared composable
не может использоваться для непосредственного обмена данными между компонентами. Он может только передавать данные во внешний сервис, и получать их оттуда. Даже vueuse/useLocalStorage
так работает. И если передача не удалась - это ошибка выполнения программы.Но, опять же, если подумать, то данная логика (оптимизация работы с внешним сервисом) очень похожа на логику работы глобального лоадера. И реализована может быть так же в несколько строк, безо всяких
effectScope
и прочих заморочек - простым и понятным кодом. Нету там ничего из Composition API
, что надобилось бы для реализации данной логики. Обычный модульный реф и синхронный код для отслеживания числа подписчиков с подключением/отключением этого рефа к внешнему сервису.Ref
, reactive
, shallowRef
, watch
и computed
должны покрывать 99.9% потребностей прикладного программирования на Vue.js
. Не надо делать простое сложным.Shared composable
как он есть - изначально неудачное название и ненужная структура. Предлагается не использовать.#composable #reactivity