Vueist
872 subscribers
12 photos
33 links
Vue шитпостинг, желтуха, советы и мысли

Дополнительный канал к @zede_code от @zede1697
Download Telegram
Provide/inject.
Часть 1: Основы использования

Сегодня затронем тему с которой чаще всего ко мне подходили люди с удивлением: как так, ты призываешь использовать provide/inject это же кошмар. Далее следует обсуждение в котором выясняется, что у человека табу на provide/inject появилось в момент еще изучения Vue2 или изучения Vue по материалам актуальным для Vue2. Также я не совсем согласен с некоторыми рекомендациями в документации, они хороши, но только когда мы используем provide/inject сами по себе, вне контекста моих советов.

Но для начала я должен успокоить тех, кто пришел из Vue2 и все еще боится использовать столь мощный механизм во Vue3:
1. Прекрасно типизируется
2. Дружит с реактивностью замечательно (хотя конечно есть способы сломать ее)
3. Имеет в подспорье композаблы, а не миксины для удобной работы с ними
4. За счет изоляции внутри компонента менее магический (речь о том что ты не можешь инжектить себе в этот же компонент что ты запровайдил)
5. Вместо строк нам доступны ключи-символы, что снимает вероятность получения коллизий

Отлично, теперь когда мы разобрались с тем почему миксины во Vue2 и Vue3 совершенно на разных уровнях. я даю список рекомендаций по использованию:
1. Использовать TypeScript (да-да это тот самый способ добиться корректной типизации provide/inject)
2. Всегда использовать ключи символы
- так как это убережет вас от возможных коллизий
- Повысит изоляцию, так как без доступа к символу никто не сможет считать значение
- Дает возможность использовать типизацию в полной мере
3. Всегда использовать ТОЛЬКО внутри композаблов
- прячем такие кишки под капот
- ограничиваем API для взаимодействия с нашим контекстом, теперь в композабле вы определяете как можно пользоваться вашим provide/inject, а не "бросаем что-то куда-то пусть используют"
- это уберет необходимость экспортировать символ (держите его всегда "в секрете")
- вы сможете в нем обработать любые ситуации (например как поступить если такого ключа нет?)
4. Делайте раздельные композаблы по мере необходимости. Например разделение на того кто может провайдить данные и композабл для тех кто его инжектит
- вновь позволит сохранить вам удобное API
- это безопасно и не вызовет каши в вызовах

На самом деле тема крайне обширная и в 1 пост ее не уместить, но эти несложные 4 правила уже превратят страшный provide/inject в одного из лучших друзей, сохранят предсказуемость и прозрачность в вашем приложении.

Следующие темы:
- Где и когда использовать?
- Продвинутое использование
- Полноценное DI на provide/inject

PS. попробую ввести теги для вашего удобства
#di #my #learn
👍327🔥6🍌1👀1
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
🔥27🍌2
Provide/inject.
Часть 2.1: Когда НЕ НАДО использовать?

Мы разобрались с основными мотивациями для использования. Теперь разберемся, когда использование provide/inject либо не имеет смысла, либо будет вредоносно.

1. Пункт специально предназначенный для реактеров. НЕ НАДО использовать контексты как глобальное хранилище и пихать в них все, что нужно глобально. Для этого есть множество других способов (да даже переменные на уровне модулей). Конечно, у вас будет работать все как и задумано, но вам не захочется использовать это таким способом (если вы прочли 1 часть), так как это будет крайне избыточно, да и профитов вы от этого не получите.

2. Контексты это не замена пропсам/ивентам, это принципиально другой механизм, это скорее способ установления множественных связей те когда МНОЖЕСТВУ компонентов в поддереве нужна связь с ОДНИМ компонентом родителя, а не 1 к 1(в случае плагинов можно считать что это связь ПРИЛОЖЕНИЯ и компонентов использующих API плагина). И у данных соединенных контекстом должна быть четкая цель для этого, а не просто экономия на создании пропсов. Стоит задуматься о "уходе от пропс дриллинга", если вам приходится заводить пропсы которые не имеют никакого смысла для промежуточных компонентов, кроме как быть прокинутыми еще дальше, в этом случае подумать о переходе на контексты можно, так как это значит, что вам необходима именно сквозная связь компонентов.

3. Не бросайте в контексты все подряд. Очевидное, но важное пояснение. Старайтесь удерживать количество контекстов минимально необходимым. Так как мутации в контекстах менее явные и не логгируются девтулзами, то лучше этот объем снижать, чтобы не превратить вашу кодовую базу в клубок из мутаций. Опять же, вам тут поможет четкое разделение по композаблам и использование контекстов только через них. Те если у вас есть ПРОСТАЯ возможность не использовать provide/inject НЕ ИСПОЛЬЗУЙТЕ ИХ. Но и не демонизируйте избегая контексты любыми путями. Например модульная переменная с точки зрения прозрачности использования не особо лучше помогает понять кто ее мутирует, а вот пропсы/ивенты делают это более явным. Но и 3 уровня бессмысленного прокидывания пропсов до целевого компонента сильно лучше ситуацию не сделают. Однако тут у меня нет для вас однозначного рецепта, сколько уровней и когда дают смысл к использованию, все-таки построение архитектуры во многом основывается на опыте и вкусе разработчика, а не четкая блок схема когда и что использовать

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

#di #my #learn
🔥201💯1
В чате закинули интересную тему. 2 подхода к извлечению данных о текущем роуте: Props vs Composables

1. Composables
Это доступ к значению напрямую через API роутов
const route = useRoute()
const currentProductId = computed(() => route.params.id)

Тут мы достаем из id указанный в URL (также можем брать метаданные и тд)

2. Props
Но нам из коробки доступен более "нативный способ" получения параметров в компоненте-странице:
const id = defineProps<{
id: String
}>()

Да, данный способ доступен лишь в компоненте непосредственно являющимся корневым для страницы, но вы можете дальше использовать его по вашему усмотрению (например настроить сервисы/сторы для работы с этим id). Также в настройках роута можно тонко настроить что и как будет лететь в пропсы компонента
// /search?q=Hello
const routes = [
{
path: '/search',
component: SearchUser,
props: route => ({ query: route.query.q }
}
]


И как часто бывает, то однозначного ответа как лучше использовать - нет.
Вариант с композаблом будет работать везде, его можно обернуть в свой композабл для работы с роутами и прочими API, а вариант через пропсы смотрится приятнее и менее перегруженный.

Поэтому у меня тут не столько пост, сколько опрос, а что предпочитаете вы?

#router #poll
🔥10🥴5
Эван тоже не лишен чувства юмора

Уже готовлю миграцию своих проектов на Godown
😁24
И вот в полку инструментов которые уже используют Rolldown прибыло. Надеемся на скорейший релиз vite+rolldown.

Только что на него переехал vue-create(раньше был на esbuild). В остальном релиз скорее связан с улучшением дефолтного конфига ESLint

#rolldown #release
🔥10👍1
Provide/inject
Часть 3: Используем API на практике

Во Vue у нас есть Suspense, но он уже кучу лет висит в Experimental, да и не нужен он особо сейчас во Vue в текущем виде (данное обсуждение я бы вынес в отдельный пост). Однако, что нам делать если мы хотим определять лоадеры в родителе, а дети подгружали бы данные и не парились насчет кто и как показывает лоадер и это вместо того, чтобы делать парады спиннеров (когда каждый компонент имеет свой лоадер) или 1 глобальный лоадер перекрывающий все приложение. Вот с таким запросом заходили в чате.

И решение достаточно простое:
1. Пусть компонент который может показывать лоадер запровайдит API ниже через useLoaderProvider
2. Дочерний компонент через API сможет его подгрузить через useLoader и достать оттуда функцию wait, которая принимает Promise и сообщает родителю, что мы грузим какие-то дочерние данные
3. Соответственно родитель может знать о всех загрузках и показывать Loader когда необходимо

Однако у этого решения есть 2 специфичных минуса
- При первом рендере родителя он еще не знает будут ли грузиться дети (можем первый рендер вообще ничего не рендерить как пример)
- Мы не можем показывать loader / дети по условному v-if и нам нужно думать, как их отображать (например через v-show)

И вот получается базовая реализация. Изучите ее пожалуйста, так как в ней использованы все советы из прошлых постов.

Однако, как поведет такая реализация себя если компонент с лоадером мы вложим в компонент с лоадером? Сейчас каждый компонент с лоадером порождает независимый лоадер: то есть лоадер выше не знает о загрузках которые идут от лоадера ниже. И иногда данное поведение нас устраивает, а что если мы хотим, чтобы наш компонент показывал Loader даже, когда грузятся внутренние лоадеры? В этом случае мы могли бы просто не использовать provide во внутреннем лоадере, если он увидит уже запровайженное значение. Таким образом получаем улучшенный пример.

Теперь мы имеем достаточное простое и лаконичное API для работы с лоадерами на проекте при этом обладая полной гибкостью в работе с ними. И такой подход было бы крайне затруднительно реализовать без механизма provide/inject

#di #my #learn #example
🔥21👍6🤨2
Наглядный key

Этот пост больше направлен для начинающих, которым нужно разобраться в концепции key во Vue. И сделаю я это через вот этот пример. В нем я реализовал 4 основных "способа" установки ключей в списках.

1. Это классический-правильный: мы ставим индекс по уникальному ID квадрата. Мы можем заметить, что квадраты при обновлении корректно перемещаются, а при пересоздании заменяются на новые, также корректно ведут себя при добавлении в начало и конец списка

2. Это вариант без установки key вообще. Мы видим, что квадраты корректно обновляются, но если квадраты пересоздать, то они посчитают это тоже обновлением и переместятся (те ноды останутся прежними), в случае добавления в нового элемента в конец - все корректно, в случае добавления в начало, то элементы змейкой передвинутся к месту ранее более высокого индекса

3. Вариант с ключом по индексу - по факту почти тоже самое, что без индекса

4. Вариант с рандомным key - ну тут полный треш, на любое действия элементы пересоздают и никаких анимаций вообще нет.

Итого: 1ый вариант нужно использовать по возможности.3ий вариант более предпочтителен чем второй, так как он явно показывает ваше намерение, однако применять его стоит лишь, когда вы уверены в статичности элементов списка (всегда конкретное количество) или идет добавление всегда только в конец

Поиграйтесь и поизучайте пример (на самом деле там достаточно интересных техник использовано, например новые cqw/cqh единицы измерения в CSS). И вам станет кристально понятно что и зачем нужен key

Небольшое дополнение о механике работы key. Key это не просто "помочь vue рендерить оптимизировано" или подобные ответы, а это буквально способ дать id нашим элементам и дать возможность vue корректно реагировать на их изменения/перемещения. Также если вы используете key вне списков, то это способ форсированно пересоздавать компоненты (соответственно при смене key произойдет полный цикл с размонтированием старого элемента и монтированием нового, а не просто "форсированный апдейт")
🔥17👍85🤔1🤨1
У нашего друга Володи(вы его можете знать как Душный Вуй) поганый телеграм каким-то образом снес канал (он просто исчез в момент и все, поддержка молчит)
Володя вел интересный авторский канал посвященный разработке на Vue
Но Володя не растерялся и создал новый (он перенес старые посты, но комменты к ним не привязаны)
Давайте поможем восстановить подписчиков

Просим дружественные нам сообщества сделать репост
https://t.me/stuffy_vuejs
19🤯1
Всем привет. Меня не было какое-то время (2 недели), да был отпуск, но фактически было путешествие по конференциям и теперь я готов продолжать писать новые посты (во время поездки это было слишком затруднительно).

А сейчас некоторые моменты:
1) Был на конференции Holy.js, где был членом ПК и экспертом, как всегда получил невероятный заряд от ребят. Также там была команда Msk Vue.js(+ с ними был уже знакомый нам Душный Вуй) с которыми я также активно взаимодействовал. кроме этого в день конференции удалось накидать мини-доклад на открытый микрофон о Vue. Я очень надеюсь, что мини-доклад смогу развить в полноценный и реализовать его уже серьезно.
2) Был на конференции Go Cloud от cloud.ru. Там я уже был чисто гостем, но просто посетить мероприятие было бы слишком скучно, поэтому с ребятам из сообщества IT-хохяев (в том числе Siberia can code) делали стрим прямо с конференции и побыли в роли "репортеров". Встретили людей совершенно разных направлений и просили их рассказать о своей работе
3) Был на подкасте от cloud.ru, где записали подкаст о Vue и влиянии AI. Много чего не рассказали из того что хотелось из-за тайимнгов, в остальном все прошло супер.
4) Был на Стачка в роли Эксперта секции Frontend. Тоже 3 дня в Ульяновске прошли сумасшедше. На доступном мне уровне как мог просвещал в промежутках о Vue.js и его преимуществах
5) Записали подкаст Тяжелое Утро (в нем вкраплений про Vue было минимум (( )

И на самом деле это не совсем конец. Так как я уже приступил к написанию доклада к ребятам из Msk Vue.js, думаю совсем скоро они сделают анонс и расскажут о предстоящем мероприятии. Кроме этого хочется придумать доклад для уже следующего сезона Holy.js по Vue.js и тут мне нужна ваша помощь, накидайте идей в комментариях о чем бы хотели услышать на этом докладе.

PS. Если же у вас уже есть идеи и вы хотите выступить сами, то форма подачи заявки Holy.js уже работает. По любым вопросам связанным с подачей и помощью с подготовкой докладов можете трясти меня в ЛС и комментариях

#личное
🔥134
@click="router.push('/hell')"

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

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

еще раз. если видите что-то подобное
@click="router.push('/smth')"

То приложите усилия, чтобы это стало <RouterLink>-ом или на крайний случай <a>, таким образом вы сделаете мир чуточку но лучше (и никто не захочет вам пожелать отдельного котла)

#remainder #learn #ux
👍45💯12🥰32🫡1
Forwarded from MSK VUE.JS News
Всем привет 🙂
Это мы идем с крутыми новостями🤪

Алярм: мы открываем регистрацию на новый митап!

📆 29 мая 2025, 19:00

📍 Мск, Крылатская 15, Офис Lamoda

👉 РЕГИСТРАЦИЯ👈

В 13-ый раз команда сообщества MskVue.js соберет единомышленников в офисе Lamoda!

Вас ждут 3 доклада, розыгрыш мерча за лучший вопрос спикеру и просто тонна общения с крутыми разрабами 🙂

Совсем скоро мы представим наших спикеров, поэтому не переключайтесь 🙂

А еще, самое время зарегистрироваться на митап и забить место в своих календариках, чтобы не пропустить этот движ, ведь количество мест ограничено.

Передаем привет главному спонсору #13 митапа - Lamoda Tech 💚

Увидимся совсем скоро 🤍
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18👍4😢1
С постами туго, так как готовлюсь к митапу ссылка на который выше, скоро там будет уже анонс доклада (по секрету это о работе с композаблами).

Но только вот не у всех есть возможность оказаться в каком-то городе для оффлайн мероприятия (на мероприятии выше трансляция и запись будет). И вот я наткнулся на еще один митап: Vuejs Talks от кор команды Vuestic UI. Митап проходит в онлайн формате на английском, так что это шанс получить общение или даже выступить впервые на английском языке (я себе галочку уже поставил, что планирую это сделать).

Самая классная часть, что проводится митап регулярно фактически каждый месяц. Следующий митап будет 18 июня.
Зарегистрироваться можно здесь
Если же захотели стать спикером

PS, а еще как член ПК Holy.js я бы очень сильно хотел видеть заявки на доклады по Vue экосистеме у нас. Поэтому если у вас есть идеи или желания, то welcome (возможно даже выступление удаленно)

#мероприятия
🔥93
Невнимательность и реактивность

Недавно в чате человек столкнулся с проблемой, что "меняя нереактивный массив он видел изменения в рендере". В чате сразу начали возникать: мол раз reactive был передан, то это уже реактивный массив. Давайте разбираться

1. Меняется ли исходный объект при передачи в reactive?
Нет. Объект сам не меняется, однако Proxy создаваемое от reactive будет мутировать именно переданный объект. Возможно это очевидно, но:
- во Vue2 редактировался исходный объект. Там каждое поле объекта становилось getter + setter (при этом во всю глубину) и конечно же такой подход имел свои последствия.
- В других фреймворках, например Svelte может быть иное поведение. Там Proxy лишь основывается на начальном объекте и мутации не идут в исходный объект

2. Отслеживает ли Vue мутации в исходном нереактивном объекте?
Нет. Однако, Proxy все-таки основан на оригинальном объекте и если кто-то изменит объект, а потом это значение прочтут реактивно, то, конечно же, будет получено актуальное значение
const a = { hello: 0 }
const aReactive = reactve(a)
const b = ref(2)
const mult = computed(() => aReactive.hello * b.value)
console.log(mult.value) // 0 * 2 = 0
a.hello = 2
console.log(mult.value) // все еще 0, Vue не знает об обновлении
b.value = 1
console.log(mult.value) // 2 * 1 = 2, так как изменилось другое реактивное значение, то Vue пересчитал computed

Кажется очевидным, но в Svelte опять же после создания реактивного значения связь с нереактивным теряется

Вот по сути 2 ключевых момента которые ввели в ступор разработчика, он не заметил, что каждую секунду из-за useFps у него происходил ререндр компонента и не мог понять почему видит обновления в нереактивных данных.

Однако затронем пару еще интересных моментов:

Знает ли Vue, что уже существует Proxy для отслеживания конкретного объекта?
Да. Vue имеет специальные WeakMap-ы со всеми существующими Proxy от реактивности (но доступа к ним прямого нет, он спрятан в исходниках @vue/reactivity)
Проверить это достаточно легко:
const a = { hello: 0 }
const aReactive1 = reactive(a)
const aReactive2 = reactive(a)
console.log(aReactive1 === aReactive2) // true

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

Есть ли какие-то данные в Proxy от reactive которых нет в исходном объекте?
Есть, их не существует в объекте, но Proxy особым образом проверяет на доступ к ним. И это ReactiveFlags и хотя у вас есть доступ к этим флагам, все-таки лучше использовать соответсвющие утилити функции от Vue
console.log(aReactive[ReactiveFlags.IS_REACTIVE] === isReactive(aReactive))
// и тд


#learn #reactivity
🔥27👍84
выступаю с минуты на минуту
🔥13👍2
Прерываюсь с отпуска с очень грустной новостью: NuxtLabs де-факто на зарплате у Vercel теперь. Я не буду тут описывать почему это плохо. Кто понял тот понял. Но на зарплате Vercel-я теперь все основные Nuxt мейнтейнеры: Энтони, Пуя, Себастьян и Даниель.

https://github.com/nuxt/nuxt/discussions/32559
#iwanttocry
😢19🤬9😱4🍌3😁2🤩1
Отпуск завершен. Возвращаюсь в рабочий ритм. Но сейчас самое главное то о чем многие меня спрашивали и ждали.
Я собираюсь сделать новый цикл интенсива по вкату во Vue. Сейчас это не объявление набора, но ждите его примерно с 10-ых чисел августа.

Для кого:
1) Те кто уже умеют писать на других фреймворках, но ему любопытно познакомиться со Vue.
2) Вы уже имеете неплохую базу JS/HTML (уровень умение пояснить за стрелочную и обычную функцию, а также знание основных HTML-тегов).
3) Вы уже пишете на Vue, но недавно или боитесь что у вас много пробелов (будем прорабатывать базу).

Формат: звонок с группой, но стрим будет и общедоступный
Домашняя работа: будет, но проверка по желанию
Протяженность: 2 недели, +- каждый день по 2-3 часа по вечерам.

Что узнаем:
1) Получим основную и прочную базу по Vue
2) Получим набор бестпрактисов для проектов
3) Ознакомимся с основной окружающей экосистемой

Чего не будет:
1) Тестирования (это заслуживает отдельной работы)
2) То что полезно при написании своих библиотек/ui либ (Storybook, tsup и тд, потребует слишком много специфичных моментов для сжатого интенсива)
3) Глубокой подкапотной работы механизмов Vue (однако база будет дана достаточная для применения на практике)

Это будет не курс, скорее обкатка некоторых элементов с него.
И это будет совершенно бесплатно и в открытом доступе, сугубо из желания увеличить количество учебного материала по Vue
🔥70🫡118❤‍🔥1💅1