Как стать автором
Обновить

Комментарии 9

А какой, собственно, профит от того, что теперь у нас это поле стало рефом (причём неявно)?

ну как же
использовать в компонентах, очевидно)
сервис можно использовать делая provide/inject локально или глобально, через плагины, например
я довольно часто использую этот паттерн, не все же хранить в одном сторе и компонентах

А какая причина хранить глобальное состояние не в сторе?

причина в том, чтобы инкапсулировать кусок логики в одном месте - тогда его можно будет, например, отделить от приложеиня в отдельный модуль, в другую библиотеку, использовать в другом проекте etc
ну вот пример, у вас есть кусок переиспользуемой логики
возьмем что-то из моего недавнего опыта - инстанс socket.io
вы хотите, чтобы состояние сокета - как минимум статус соединения - было реактивным
со стором у вас два варианта
1 хранить инстанс socket.io в сторе и осуществлять все операции с помощью action-ов
2 держать логику socket.io в классе, а его состояние коммитить в стор
в обоих случаях вы не сможете это легко куда-то вынести
а вот класс можно легко
вообще сейчас более популярен подход использовать use-функции, аля useSocket(), см. https://vueuse.org/
но это уже кому как удобнее: функциональный стиль или ООП
в статье я по сути описываю, как с ООП делать функционал, аналогичный use-функциям

ну вот как раз композаблы (use-функции) это общеизвестный паттерн. Когда мы видим функцию useFoo, мы понимаем, что это композабл. Мы ожидаем, что она будет принимать/возвращать рефы и осуществлять какие-то реактивные операции.
А тут у нас есть класс, о котором мы можем только догадываться, что его поля реактивно связаны с чем-то

  1. Осторожнее с декораторами, они не зря имеют экспериментальный статус. Основная проблема с ними в том, что если вы смешиваете декораторы и наследование, то можете получить крайне занимательные баги в будущем.

target.__refs = target.__refs ?? {}

Не очень хорошо влезать в структуру чужого объекта. Я бы предложил использовать WeakMap вместо этого:

const metaRefs = new WeakMap();
// ...
function initRefs (target: any, key: string, value ?: any) {
  if (!metaRefs.has(target)) {
    metaRefs.set(target, shallowRef(value));
  }
}
  1. Вместо декораторов можно использовать более стабильный и универсальный способ - Proxy. Кроме того, он будет работать и без TypeScript.

с WeakMap неплохая идея, только пример надо поправить, должно быть что-то вроде

const metaRefs = new WeakMap();
// ...
function initRefs (target: any, key: string, value ?: any) {
  if (!metaRefs.has(target)) {
    metaRefs.set(target, new WeakMap());
  }

  const metaRef = metaRefs.get(target);

  if (metaRef.has(key)) {
    metaRef.set(key, shallowRef(value));
  }
}

насчет Proxy - не уверен, что с его помощью можно столь же удобно добавить реактивность в уже существующие классы. Если я правильно понял, вы предлагаете что-то вроде

const reactiveClassInstance = new Proxy(nonReactiveClassInstance, {get, set...})

но в таком случае нужно делать достаточно сложный factory и, что самое неприятное, во всех местах, где используются исходные классы, заменять их на реактивные прокси и не забывать делать это в будущем, что суть человеческий фактор и источник ошибок

Мне одному Composition Api кажется порочной технологией?

Всю жизнь программисты борятся со сложностью кода. Реактивное программирование уже даёт определённый скачок сложности, по сравнению, скажем, с процедурным, т.к. много вещей происходит "неявно", обеспечивается фреймворком, и это надо держать в голове и учитывать. Чтобы бороться с этой сложностью люди придумал всякие Flux паттерны, натянули мввм на компоненты, выстраивают жёсткую архитектуру и задают ограничения контекстов - используя иерархическую структуру компонентов и модулей, микрофронты, гексагоналку и т.п.

И тут вылезает технология, которая позволяет связать реактивно что угодно с чем угодно. И ты вот такой меняешь одно поле в классе и у тебя может поменяться в приложении всё что угодно и где угодно, причём это неявный вызов, отследить это возможностей крайне мало. Т.е. очень легко неправильно заиспользовать и вероятность получить тяжело поддерживаемый код с высокой связностью крайне высока. Так надо ли оно?

Обычно когда возникают вопросы с тем, что "сложно реиспользовать код" - это вопрос к тому, что кто-то либо наговнокодил, либо просто накопился тех.долг и текущие компоненты и модули надо либо делить на несколько, либо объединять в общий, и после рефакторинга оказывается что никакие такие дополнительные горизонтальные связи не нужны.

Странная тема, для этого есть либо store, либо composables. Сам факт наличия с сервисах реактивных свойств, у меня вызывает вопросы. Я бы сказал что это ошибка архитектуры.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации