Vueist
902 subscribers
13 photos
36 links
Vue шитпостинг, желтуха, советы и мысли

Дополнительный канал к @zede_code от @zede1697
Download Telegram
Главные слабости шаблонов Vue: Переиспользование одного блока кода в 2+ местах

Как и ожидал, прошлые проблемы не воспринимаются многими как проблемы, особенно если они пишут только на Vue. У вьюшников уже выработанная ментальная модель обхода таких ситуаций. Однако рассмотрим как решить эту проблему для тех, кто еще не сильно знаком со Vue:

issue

<a v-if="condition">
<!-- Part A -->
</a>
<template v-else>
<!-- Part A -->
</template>

Мы видим, что какой-то блок кода может повторяться в коде компонента 2+ раза и что же мы можем с этим сделать?

1. Очевидный copy-paste
<a v-if="condition">
<div class="card"> {{ text }} </div>
</a>
<template v-else>
<div class="card"> {{ text }} </div>
</template>

Когда информации не так много, то мудрить и не надо, просто копируем и вставляем
+ моментальная реализация
+ легко понять
- нужно следить, чтобы значения всегда были одинаковыми (а быстрый хот-фикс легко такое ломает)
- это некрасиво, чем больше кода тем больше это попахивает
- это усложняет чтение с размером такого блока

Поэтому данное решение оптимально для случаев когда информации имеет смысл продублировать совсем немного

2. Вынос в компонент
Ощущается как самый лучший вариант. Мы же делаем декомпозицию! Разбиваем блоки!
<a v-if="condition">
<MyScopeCard :text />
</a>
<template v-else>
<MyScopeCard :text />
</template>

И вроде действительно решает 80% потенциальных проблем. Остается лишь вынести все данные в пропсы / слоты, / ивенты / модели

+ очевидное решение
+ не самая сложная реализация
- Такой компонент не всегда имеет целостность, те по факту он сугубо оказывается прибитый гвоздями к конкретному компоненту и без него не имеет смысла
- Если нужно прокидывать много данный то приходим отчасти к варианту 1, нам все также нужно следить за идентичностью передаваемых пропсов и слотов
<a v-if="condition">
<MyScopeCard :text :user @save="onSave" @load="onLoad" ... />
</a>
<template v-else>
<MyScopeCard :text :user @save="onSave" @load="onLoad" ... />
</template>

- Это плодит порой излишние сущности, даже там где они особо не нужны (если нам нужно обернуть кусочек в ссылки или не делать его ссылкой по условию, то это не звучит как повод выделять это в отдельный компонент, да-да можно пойти от обратного и вынести в компонент <ConditionalWrapper wrapper="a" :condition >)

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

3. использовать createReusableTemplate
<script setup>
import { createReusableTemplate } from '@vueuse/core'

const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
</script>

<template>
<DefineTemplate>
<!-- Part A -->
</DefineTemplate>

<dialog v-if="condition">
<ReuseTemplate />
</dialog>
<div v-else>
<ReuseTemplate />
</div>
</template>

+ все связанные данные остаются в рамках компонента в котором они имеют смысл (однако тщательно обдумайте вариант 2, возможно вам действительно нужен отдельный компонент)
+ мы не плодим лишних сущностей
+ у нас есть лишь 1 копия и нам точно не надо париться об переиспользовании
+ подход крайне гибок, но за счет избыточности его не хочется применять на каждый чих (меня радует в этом плане баланс)
- требует зависимость
- обладает некоторой избыточностью с небольшим "протеканием" шаблонов в script
- осуждение от коллег придерживающихся подхода, что можно применять вариант ответа только 1 или 2

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

Есть конечно и другие варианты
1) Ухитриться использовать <component :is="condition ? 'div' : 'a'">, но он не всегда возможен, особенно если они расположены раздельно или template это псевдо-компонент и указать его там не выйдет
2) Использовать <script setup lang="jsx"> и описать на JSX, стоп, вы действительно хотите смешать 2 стиля шаблонов в 1 файле?
3) Переразбить компоненты так, чтобы внешняя часть стала утилитарным компонентом (пример с <ConditionalWrapper wrapper="a" :condition >)

В коммах оставлю как это решается в других типах шаблонов
👍16🔥41❤‍🔥1🤔1
Nuxt: Compodium

Nuxt можно много за что не любить. Но что я люблю в Nuxt, это какие классные решения они приносят в мир Vue и не только

Я давно восхищаюсь проделанной работой над Nuxt DevTools и сейчас это без сомнения самые лучшие DevTools из всех что существуют для фронта и одна из причин это возможность встраивать кастомные расширения в него же. И сейчас речь идет об одном из них: Compodium

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

Проект пока на ранней стадии. Но вы уже можете начать отслеживать как оно продвигается и поиграться с демкой на CodeSandbox.

Магия работает на основе метаинформации компонента и использования дополнительной функции в компоненте
extendCompodiumMeta({
defaultProps: {
propName: provDefaultValue
}
})


Все остальное он подтягивает сам. Пока на этом функционал заканчивается, но я надеюсь, что он вырастет.
🔥28
Нам пообещали новую версию Vue Language Server. Пока не знаю что от нее ожидать, но попытка заигрывания с TS сервером стоила Vue многого, надеюсь это исправит главную причину нестабильности в плагинах Vue
🔥19👀62💅1
Глубокий Vue

Как изучать Vue разработчикам с опытом которые уже доки знают неплохо, но хотят двигаться дальше?

Самый логичный ответ: вперед штудировать исходный код Vue!
Отличный вариант но... это весьма муторно и трудоемко, а многих в целом может отпугнуть от погружения

Неужели нет годных статей и выступлений? Есть, но выискивать их трудно, а следить за их актуальностью и появлениями еще сложнее. Неужели нет варианта лучше?

На самом деле есть: это подход create from scratch(создать с нуля)
Те мы берем Vue и пытаемся воссоздать его с самого нуля тем самым знакомясь с его механизмами и почему были сделаны те или иные решения.

К счастью, уже есть проект который сосредоточен на объяснении всего этого доступным языком: chibivue. Книга готова не на 100%, но большая часть уже проделана и возможно к определенному моменту вы и так будете готовы к чтению исходников. Что хорошо в книге не только теория, но и большое количество примеров с плейграундом. С ней вы создадите Vue самостоятельно и познакомитесь как все работает под капотом.

Кстати, проект затрагивает исходники не только Vue, но и других проектов:
- изучение исходного кода Vapor
- пишем свой VueUse (проект в глубокой разработке еще)
- nuxt (проект в глубокой разработке еще)
- vite (на зачаточном этапе)

PS Запили с нейронками RU версию chibivue
PPS Так-то и английская версия сайта это результат работы нейронки(переводится через GPT-3.5 автоматизированно), оригинал пишется на японском
🔥408😱3💅2👍1
Lynx-vue

Я думаю многие слышали о выходе Lynx (считайте что это "убийца" ReactNative от ByteDance(TikTok)). Ключевая особенность Lynx в том что он не привязан к jsx и может использовать любой формат (как и в NativeScript), но из коробки официально Lynx идет с React-like API (на самом деле на основе более легковесного Preact).

Соответственно Vue у которого для нейтива только всякие capacitor, cordova и прочие их производные, а Vue+NativeScript(nativescript-vue) все еще сырой, то нам нужна достойная альтернатива для кроссплатформы и вот Lynx дал прекрасные шансы для этого.

Итак к делу: [Feature] Vue Integration
Это ишьюс по добавлению интеграции Vue официально. Давайте поддержим лайками (НЕ ПИШИТЕ +1 В ИШЬЮСЕ) и будем верить, что это найдет какую-то реакцию (если она будет, то я вам сразу сообщу :D)

А это точно иммет смысл просить? Однозначно, никто за язык не тянул их)
It’s probably less than one would think… we already had production uses or prototypes for Solid and Vue flavor before making that statement in our blog


Что насчет других фреймворков?
- Svelte [issue]
- Solid.js (обсуждение на reddit)
- Angular (ничего толкового не нашел)Й
🔥26👍6
Дождались! NativeScript-Vue 3.0 вышел из беты (которая длилась почти 2 года).

Для тех кто не знаком с NativeScript, это попытка сделать "интероп" на JS между нативной частью приложений и JS.
У вас сохраняется поддержка CSS, но при этом вы можете собирать приложения для Mobile/Web на нем же. А соответственно NativeScript-Vue это прослойка для поддержки Vue3 в NativeScript

- Чем принципиально отличается от PWA и Cordova/Capacitor?
- Это не WebView, соответственно он ближе к нативной платформе и вы можете использовать нативные плагины с ним достаточно легко. Соответственно при использовании конкретных компонентов также будут использоваться системные компоненты из соответствующей OS

- А будут ли у меня DevTools?
- Да поддержка Vue Devtools имеется

- А насколько его можно уже использовать?
- Заявлено уже, как feature-complete. Проект был достаточно долгое время в бета-версии, так что надеемся на относительную стабильность. Я же скажу, что инструмент не самый популярный, поэтому для чего-то серьезного лучше отнестись к нему особой осторожностью, а вот реализовать на нем пет-проект, почему бы и нет

В целом радостная новость, что наконец-то у Vue3 появляется хоть что-то для противопоставления ReactNative, который доминирует в мире JS-кроссплатформы (и в целом имеет нехилую популярность в мире кроссплатформенных решений)

P.S. Хотел немного актуализировать дела и по Lynx, но там так и не появилось действительно стоящих сигналов, все что могу сообщить, есть попытки переноса, но до чего-то реально рабочего там пока далеко. Эван Ю и команда Lynx заявляют о готовности предоставления помощи с разработкой, но каких-то официальных анонсов или новостей об официальных разработках не было (хотя из X есть информация, что команда Lynx запускала прототипы с Vue)
👍15🔥5😨3🦄1
State of Vue 2025

Вы точно слышали об опросах State Of JS/CSS и тд вплоть до React и AI. Vue же под конец прошлого года тоже делал свой опрос.
И вот наконец-то появились результаты. На самом деле очень объемная статья с результатами, так что TLDR выдать сложно, но я пытаюсь пройтись по интересным моментам:

1. Интервью с Эваном.
В целом ничего нового тут нет. +- все это он говорил и на других интервью и выступлениях: оптимизация реактивности в 3.6, Vapor Mode и что он сейчас главный фокус команды. Вот разговоры относительно VoidZero были интереснее. Достаточно много деталей было сказано относительно бизнес модели: тут он повторил слова, что в планах делать какой-то узко-заточенный туллинг для энтерпрайза и этим монетизировать open source разработку. Заверяет, что наличие каких-то платных решений никак не скажется на открытой части и он ставит всю свою репутацию на это.

2. Vue в цифрах
- Согласно статистике BuiltWith Vue наиболее популярен в США (1,8кк) Германии (161к) Китае(127к) РФ(100к) и Англии (96к).
- Неплохая статистика относительно популярностей фреймворков
- Зависимости в NPM. Тут скорее удивил React, который с 2022 года с 84к зависимыми от него пакетами вырос до 240к в 2024. У Vue c 53к до 80к
- W3tech статистика показывает, что Vue пользуется популярностью у сайтов с высоким трафиком, значительно обходя в этом показателе React (передаем привет любителям мантры про Vue для маленьких проектов)
- Ванильный Vue предпочитают гораздо больше чем мета-фреймворки. Самая читаемая статья на сайте, это про интеграцию с Laravel
- На данный момент сертификаты разработчиков получили более чем 900 разработчиков (и проценты в 80%+ относительно удовлетворенностью сертификацией) [стоит помнить, что Vue School ее организовал и поэтому заинтересован в ее продаже]

3. Результаты опроса Vue.js разработчиков
- приняло участие 1428 разработчиков. У state of react было 7,8к (но Vue опросник, мягко говоря, был гораздо менее разрекламирован)
- 96% принявших опрос используют Vue3
- 82% предпочитают использовать TS
- 80% используют Pinia для глобального стейт менеджмента
- 68% используют/ли Nuxt в своих проектах
- Статистика по Nuxt: SPA - 62% SSR - 96% SSG - 40%
- 53% принявших опрос используют Vue уже больше 4 лет (сильное отклонение в пользу опытных разработчиков)
- 98% участников используют в качестве источника знаний о Vue документацию, а курсы только 36%. YouTube же набрал только 3%
- 57% принявших вопрос указали как язык бекенда в организации.. Node.js (вот этого точно не ожидал), PHP же набрал только 37%, а golang 12%
- 35% сталкивались за последний год с Vue2.7, а 2.6- только 19%
- И теперь мякотка: 55% респондентов... из РФ (кажется мы перестарались с раскидыванием этого опроса :D)
- 33% используют Options API. 5% class based api
- 75% используют scoped стили, 7% CSS module. 56% не пишут стили (сюда попали TW и тп решения, но все равно это очень много)
- Относительно того чего не хватает разработчикам произошел сильный разброс: 21% чего-то не хватает в экосистеме (интересно чего), 15% не хватает текущих возможностей для мобильной разработки, проблемы с TS отметили 13% (что весьма мало)
- Относительно главных проблем во Vue: 25% отметило проблемы с миграцией (ожидаемо), 17% проблемы с туллингом (тут скорее всего речь о проблемах с поддержкой в редакторах), 13% находят проблему с поиском работы
- Сделали отдельную статью по решению проблем во Vue (достаточно поверхностно)
Кратко: относитесь с осторожностью к результатам. Так как участников было мало, то высока вероятность перекоса в зависимости от сообществ где продвигали этот порос (в одном только дискорд сервере Nuxt 28к участников)
🔥22👍3
4. Что нового в Nuxt
- За счет фиксированного графика релизов и их способа монетизации Nuxt не нуждается в hype-driven development
- Говорят о важности повышения стабильности релизов, повышения покрытия регрессионными тестами, изоляции экспериментов
- Все еще делают огромную ставку на UnJS экосистему, отмечая ее рост и новые пакеты

5. Миграция на Vue3 + Перфонс во Vue
Тут были рассказы от разных компаний и с какими трудностями они столкнулись при переходе на Vue3. На самом деле там каждый отчет на статью отдельную тянет, поэтому оставлю изучение ее на вас

6. Что ждать дальше?
- Vapor Mode это доказательство, что Vue открыт для изменений и значительных, глубоких улучшений при этом сохраняя стабильность и обратную совместимость
- Vue успел набрать достаточную массу контента, чтобы AI умело неплохо с ним работать. Ожидается прирост с этого направления
- Все делают очень большую ставку на Vapor моде (по моему мнению чрезмерную)

На самом деле проделана просто гигантская работа ребятами, чтобы собрать столько информации, за что им большое спасибо! Жаль, что в основном опросе было настолько мало участников, но в остальном информации и интервью было с избытком
👍21🔥10❤‍🔥1
Framer Motion Vue

Произошел официальный релиз Motion от Framer для Vue.

Что это?
Современная библиотека для управления анимациями во Vue. Изначально завоевала всеобщую любовь в мире React.
Ключевой особенностью Framer Motion это декларативный контроль над анимациями через компоненты, а не ручное управление.
Имеется широкий спектр возможностей от анимации базовых значений, до анимаций перемещений по лейаутам страницы. На данный момент это становится самой продвинутой библиотекой для анимаций созданных для Vue (тот же GSAP не имеет столь тесной интеграции со Vue, а у TresJS цель не в анимациях)

<template>
<motion.div
:whileHover="{ scale: 1.1 }"
:whilePress="{ scale: 0.9 }"
/>
</template>


На самом деле проект не новый и изначально делался в рамках экосистемы unovue и у него даже была отдельная дока. Но в последствии его забрали в основной гитхаб motion. Разработчики остались те же и они продолжают отвечать за этот же репозиторий.

Кстати говоря, это не единственная попытка выдать схожее поведение. У родственной для unovue экосистемы в виде oku-ui тоже есть свой motion. Сравнивать их я не буду, визуально по API мне больше нравится вариант oku ui в нем больше ощущается vue way, но framer motion гораздо больший по фичам. Оба в качестве ядра использовали фреймворк-агностик версию Motion. Однако дополню что oku motion сейчас в режиме архива на гитхаб, что достаточно грустно видеть

Еще одна ложка дегтя: Motion имеет платную разовую версию Motion+. В нем имеются "премиальные" возможности и компоненты, но в целом и без них прожить можно. Ценник правда ни разу не демократичный: 300 евро для 1 пользования и 1500 для компаний (10 лицензий)

Другие аналоги:
vueuse/motion - из экосистемы vueuse достаточно лаконичное и простое в использование API. В целом большую часть простых задач покроет и выполнен в "магическом стиле" присущим antfu.

встроенные возможности во Vue/CSS - в целом покрывают уже львиную долю потребностей, но могут быть несколько более объемными в описаниях и обладать ограниченной поддержкой (например @starting-style не имеет полной поддержки в Firefox)

class based animation - это любые решения опирающиеся на классы для анимаций: tailwind animation. unovue animations, animatie.css и тп. Тут обычно ограниченный набор возможностей, либо ограничения из варианта выше, зато для базовых сценариев замечательный вариант

api integration - сюда отнесем все решения которые не имеют тесной интеграции со Vue, но вы можете достаточно легко интегрировать через API их в свои приложения GSAP, Anime.js и тд

В целом, это хорошая новость для экосистемы Vue, но осадочек из-за отделения от экосистемы unovue остался. Например тот же Radix Vue смог перерасти оригинал и стать Reka ui, боюсь что с "официальной поддержкой"(менйтейнер же все равно член unovue) такого не будет возможно.
🔥23👍92
Локальные переменные в шаблонах

Вновь возвращаюсь к посту о главных слабостях шаблонах Vue(решение первой проблемы). И следующим на очереди у нас "невозможность создания локальных переменных в шаблонах".

Что это и когда оно нужно?
1. Вам нужно нужно обработать значение внутри v-for
<template v-for="item in items">
<div> {{ formatData(item).text }} </div>
<input v-model="formatData(item).value" />
</template>

2. Вам нужно обработать значение пришедшее из scoped slot
<MyComplexFrom>
<template #={ basicData }>
<div> {{ formatData(basicData).text }} </div>
<input v-model="formatData(item).value" />
</template>
</MyComplexFrom>

Так как значение прилетает к нам из вне мы не можем положить никак его в computed или попытаться мемоизировать

3. Доступ к вложенным значениям. Ситуация для опытных вьюшников почти нереальная, но подсветить ее стоит
<div> {{ item.user.info.text }} </div>
<input v-model="item.user.info.text" />
<!-- хочется условного сокращения до userText -->


А это реально проблема?
Опытные разработчики на Vue знают как ее обойти, но количество запросов на эту фичу достаточно большое (25+ по поиску в RFC и ишьюсах). И я в целом вижу запрос на данную функциональность у разработчиков, особенно в сравнении с другими фреймворками. Эван Ю же отказывался от возможности добавлять переменные в шаблоне для сдерживания количества логики в шаблонах их и мотивации разработчиков использовать другие инструменты

Как решать?
1. По возможности выносите логику из шаблонов, например в computed, это не всегда возможно (например в ситуации 2), но пока есть такая возможность это стоит использовать, особенно для 3его случая. Думаю тут все достаточно очевидно, но люди порой ленятся заниматься такими мелочами

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

Первые два решения должны быть для вас основой! Остальные решения это ближе к костылям и другие Vue разработчики могут не одобрить ваш выбор!

3. Использование хака с атрибутами.
<template v-for="item in items" :set="formatted = formatData(item)">
<div> {{ formatted.text }} </div>
<input v-model="formatted.value" />
</template>

Что это за :set=? Это какое-то специальное свойство о котором нам не сказали? Нет, вы можете использовать любой нейминг с несуществующим атрибутом. Он нам нужен чтобы заабьюзить создание локальной переменной (полностью механику раскрывать не буду, с ней вы можете поиграться в плейграунде, просто зайдите на вкладку с собранным JS). Я бы использовал этот случай только если вам нужно что-то очень быстро проверить и выпилить его из кода.

Минусы:
- неявное решение с абьюзом способа компиляции шаблона
- это все-таки аттрибут и он попадает в HTML шаблон (решение :set="void (x = y)" но это выглядит еще хуже)
- это поведение сломано в Vapor
- нет типизации

4. Использовать специальный компонент который будет прокидывать вам значение из scoped slot-а.
Решает почти все проблемы из 3его пункта:
- использует все механики честно, пусть и не самым привычным способом, поэтому сложно его сломать
- никак не влияет на HTML
- работает в Vapor (на самом деле есть там своя тонкая специфика относительно ленивых пропсов, но это скорее про перф, а не про сломанную работу)
- работает типизация

Минусы
- Дополнительный уровень вложенности в шаблоне
- Слегка бойлерплейтный
- Нужно тащить в кодовую базу или установить
- Нужно импортировать в каждом компоненте (но в теории можно 1 раз зарегистрировать его как глобальный компонент)

Стоит оно того или нет, решать вам, но если первые 2 решения не подходят, а выкручиваться надо, то однозначно лучше воспользоваться им
🔥182
Сегодня захватим много контента по новостям Vue 💚
#подкаст

Обзор State of Vue.js 2025, новый статус styled-components и обсуждение новостей JavaScript — уже через час.

Новый выпуск «Тяжелого утра» в 11:00:
на YouTube
в VK Видео
🔥134👍1
Джонсон с кем-то спорил на митапе и в процессе нашел более оптимальный алгоритм и еще большк ускорил и без того быстрый alien-signals и алгоритм вдобавок еще меньше стал весить. Все это пока нас ждет в vue3.6 однако то сколько раз за это время успели улучшить перф впечатляет
🔥17😱6👍3❤‍🔥2
Как внедрить MVC в мое Vue приложение?

Достаточно часто возникающий запрос в сообществе, поэтому я дам сразу на него ответ: НИКАК. Почему распишу ниже

Время идет и все развивается. Изначально MVC действительно создавался для упрощения создания интерактивных приложений... правда эта модель была опубликована в 1978(9) году. И для того момента это действительно был прогресс. Правда потом поверх MVC еще пошли MVP и MVVM (и все они живы и по сей день). Однако в мире веб-разработки пошли еще дальше и дошли до продвинутых концепций реактивности на основе сигналов.

И все же люди которые погружаются в изучения архитектуры сталкиваются с MVC и видят в нем "ну вот настоящая АРХИТЕКТУРА, если я затащу ее к себе в приложения, то у меня все будет хорошо и я буду крутым программистом". Но... так ли это? MVC в целом полностью ушло из мира UI-приложений, даже Angular с его четкими разделениями.. это скорее MVVM и то с натяжкой. На самом деле мы прошли еще один этап проектирования приложений благодаря Flux с его однонаправленным потоком данных (реакт тоже близок к этой концепции). Сам же Vue изначально описывал себя как идейно-близкое к MVVM. так вот подумайте насколько хороша затея уже имея MVVM пытаться насильно превратить его в MVC?

Я пытался пособирать информацию о том почему именно MVC не имеет смысла во Vue. но сталкивался с одним и тем же, любая попытка это дело соединить выглядит как усиленное натягивание совы на глобус и это просто не имеет смысла. У нас есть замечательная реактивная модель в рамках которой мы и должны описывать нашу бизнес логику и нет причин пытаться ее вырвать в чистые представления модели и тд. Вы можете если очень хотите ментально держать у себя в голове концептуальное MVC, но и в этом особого прока нет: у нас есть модель описываемая реактивной системой, компоненты в которые реактивная система встроена и управление которое происходит через туже реактивную модель.

Вы можете сказать, ну вот же все через реактивность и в итоге каша, а нет. У вас четко отдельное представление в виде рендера компонента. И в нем не должно быть бизнес логики и вычислений (по возможности), у вас есть скрипт который выступает как раз содержанием бизнес логики со всеми ее входами и выходами, которую можно разбивать используя композаблы, а "представление" может быть разбито на компоненты.

Кроме того у нас есть отдельные концепции глобального состояния и на нем уже тоже обжигались. Помню как повально с расцветом Flux пытались из глобального состояния сделать "единую точку истины", запихать в нее всю модель приложения, а компоненты делать тупыми насколько это возможно посредниками к глобальному состоянию и это было просто ужасно, писать было больно, а связи от этого становились только менее явными.

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

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

PS. Причина для данного поста и мой комментарий прикрепляю. Простите, просто уже подгорело...
13👍5🔥3💩1💊1
createSharedComposable

Если бы меня спросили лучшие паттерны для освоения во Vue, я бы точно назвал одним из них shared composable. Почему и что это за фрукт такой?

Происхождение
Первое упоминание о shared composable было в RFC Vue посвященному Effect Scope. И там говорится о примере композабла useMouse который слушает перемещения мышки и возвращает это в виде реактивных переменных координат. И вроде логично, что это не самое легковесное действие. А если это нужно множеству компонентов? Да каждый компонент использующий useMouse подписывается на него и это становится уже ощутимо. Тогда почему бы просто не вынести в глобальный STM как Pinia? Отличный вариант, но он будет работать даже когда нет никого кому нужны эти данные. И вот тут на помощь приходит shared composable он умеет как STM шарить данные на множество инстансов, но при этом если никто его не использует, то "стор" уничтожается! При этом сам паттерн универсальный и все что вам нужно это обернуть обычный композабл в createSharedComposable. И да, как только все компоненты использующие useMouse будут размонтированы shared composable тоже отпишется от событий мышки.

Как это работает?

На самом деле весьма не хитрым образом. Оно использует API Effect Scope + счетчик подписчиков, когда подписчиков становится 0 он уничтожает текущий скоуп. Вот и все. А... возможно вам не совсем знакомо что же такое Effect Scope (однажды мой доклад на эту тему уже выложат на YouTube...). А вот поэтому этот паттерн и хорош, он заставляет вас слегка заглянуть поглубже в работу Vue. Я уже приложил ссылку на RFC, где крайне подробно расписано что такое реактивные скоупы и как они работают. Если совсем сократить и упростить, то эффект скоупы это как мешок для реактивности: он запоминает все вызванные watcher-ы и уничтожает их в нужный момент (да-да именно так работает setup в компонентах). А вместо onUnmounted вы можете использовать onScopeDispose.

А чем же так крут этот паттерн еще?
1. Учебный эффект позволяющий лучше понять работу Vue
2. Возможность оптимизации как в примере c useMouse
3. Он позволяет на SPA приложениях спокойно заменить Pinia или другой STM на себя, так как спокойно выполняет обязанности глобального стейт менеджера, только еще и умеет уничтожаться когда никому не нужен (с pinia я видел как люди вручную это дело пытаются зачищать)
4. Advanced DI. По сути созданный композабл это сервис который может жить внутри provide / inject и расшаривать данные и логику как STM, но только на определенной части приложения (я не раз видело как пытаются генерировать это с pinia + id стора)

А какие есть минусы?
- Это не самое SSR Friendly решение
- Этого API нет из коробки, поэтому вам придется либо писать его самим, либо взять из vueuse
- Можно при неаккуратном использовании натворить страшных вещей
- Алгоритм использует простой счетчик, поэтому циклическая зависимость приведет к невозможности уничтожения (если не создать ручной "рубильник")

Итого: классный паттерн имеющий крайне широкие возможности с дополнительным эффектом погружения в мир реактивности Vue, однозначно рекомендую к изучению
🔥315
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