Душный Вуй
739 subscribers
150 photos
5 videos
4 files
346 links
Немного душные, но ламповые заметки о Vue.js
#vuejs #vue #nuxt #vuex #pinia #вью #vapor
Download Telegram
Forwarded from Black_Yuzia
Там https://t.me/vue_updates/370
vue 3.4.0 релизнулся.

Идите читайте changelog 👀
Чуть позже сделаю удобнее 🤔
Forwarded from Душный Вуй
#vue #console
By Michał Kuncio
Forwarded from Душный Вуй
#vite #vue

Го смотреть конфу ViteConf
https://viteconf.org/live
#vue #критика

Продолжаем смотреть ваши проектики, на очереди у нас кнопочка поделиться в соц. сетях с гигантским количеством вариантов 👀

Автор: @webistomin
Код: https://github.com/webistomin/vue-socials
Сайт: https://vue-socials.vercel.app/
Please open Telegram to view this post
VIEW IN TELEGRAM
#vue #критика

UI для мультиплеерного мода M&B:Bannerlord
Без адаптива (не нужен)
Авторизация через Steam/Xbox/Epic (чтобы увидеть все разделы)
Много unit-тестов

Автор: @zohan333

Web: https://c-rpg.eu/

https://c-rpg.eu/strategus/ - WIP режим глобальной карты

GitHub: https://github.com/namidaka/crpg
В общем телега снесла канал, так что пришлось всеми возможными силами восстанавливать как смог. Зовите друзей Вуюшников, переманивайте Реактеров, уговаривайте Ангулярщиков и приглашайте Свелтистов 😁

Давайте снова вместе вдохнём жизнь в это сообщество 💚

https://t.me/stuffy_vuejs
Please open Telegram to view this post
VIEW IN TELEGRAM
#vue

Кстати одним из вопросов в дженге было "Чем отличается watch от watchEffect", и почему-то мало людей отвечало на него, даже среди разработчиков на Вуе, так что давайте немного теории:

watch
Это такой наблюдатель который позволяет следить за чем либо, и выполнять нужные действия когда вот это первое поменяется, ну например:
import { ref, watch } from 'vue';

const count = ref(0);

watch(count, (newValue, oldValue) => {
console.log(`count изменился с ${oldValue} на ${newValue}`);
});

count.value = 1; // Вывод: "count изменился с 0 на 1"

Какие у него есть нюансы?
— Надо явно указать за чем ты хочешь следить
— Он начинает следить только при первом изменении переменной, если ты ему не укажешь immediate: true
— Могёт тебе показать как старое значение, так и новое
— Есть разные настройки, типа того же immediate, или например возможность указать когда именно должен работать watch, до рендеринга, или после

Причем, так то в watch тоже можно следить на несколькими элементами вот так
watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
console.log(`Count: ${newCount}, Name: ${newName}`);
console.log(`Было: Count: ${oldCount}, Name: ${oldName}`);
});


watchEffect
Тоже наблюдатель, вот только он умеет следить сразу за несколькими переменными вот так:
import { ref, watchEffect } from 'vue';

const count = ref(0);
const multiplier = ref(2);

watchEffect(() => {
console.log(`Результат: ${count.value * multiplier.value}`);
});

// Вывод при инициализации: "Результат: 0"
count.value = 1; // Вывод: "Результат: 2"
multiplier.value = 3; // Вывод: "Результат: 3"


Шо по нюансам?
— Не надо первым аргументом передавать то, за чем ты хочешь следить
— Он прям сразу следит за всем (не нужно указывать immediate).
— Он не покажет тебе старое и новое значение
— Подойдёт когда тебе нужно следить сразу за несколькими переменными
— Тоже есть интересные настройки типа flush для определения когда именно он должен работать
— Для отладки кстати можно заюзать onTrack и onTrigger

Ну и читаем доку конечно жи:
EN: https://vuejs.org/guide/essentials/watchers.html
RU: https://ru.vuejs.org/guide/essentials/watchers
#vue

Иногда пишешь компонент, прокидываешь в него всякие id, class, style и прочие data-*, а они куда-то теряются. А всё потому, что Vue по умолчанию не лепит эти атрибуты на все элементы подряд. Но есть нюансы 👇

Что вообще происходит?

Vue берёт все атрибуты, которые ты НЕ объявил явно в props, и добавляет их к корневому элементу твоего компонента.
<MyButton class="big red" id="super-btn" />

<!-- Внутри MyButton.vue -->
<template>
<button>Нажми</button>
</template>

👉 В итоге на кнопке окажутся и class="big red", и id="super-btn". Удобно? Удобно.

А если у меня кастомная разметка?
Если ты хочешь, чтобы атрибуты не просто свалились куда попало, а чтобы ты сам решил — кому их отдать. Тогда тебе пригодится юзать v-bind="$attrs".
<template>
<div>
<button>Жмек-с</buitton>
<button v-bind="$attrs">Жмак</button>
</div>
</template>


Иногда ты вообще не хочешь, чтобы Vue сам что-то передавал. Например, если ты хочешь полный контроль. Тогда пишешь:
<template>
<div class="wrapper">
<button v-bind="$attrs">Кнопка</button>
</div>
</template>

<script setup>
defineOptions({
inheritAttrs: false
})
</script>

👉 В этом случае все атрибуты пойдут только на кнопку, а не на обёртку. Особенно полезно, если тебе важно, чтобы стили/события применялись именно к интерактивному элементу.

Важные моменты

— Всё, что не prop — это $attrs
— По умолчанию всё это идёт в корневой элемент
— Хочешь контроль — юзай inheritAttrs: false и v-bind="$attrs"
$attrs можно использовать и в setup, и в template
— Если атрибут совпадает с именем prop — он туда не попадёт

Ну и конечно читаем доку:
EN: https://vuejs.org/guide/components/attrs.html
RU: https://ru.vuejs.org/guide/components/attrs
#vue

KeepAlive во
Vue 3 — теперь с бонусами 🎁

KeepAlive — это специальный компонент-обёртка, который позволяет кешировать компонент, когда он удаляется из DOM. То есть Vue его не уничтожает, а аккуратно откладывает "на потом". Это как display: none, только с сохранением всех данных, реактивности и внутреннего состояния.

Типичный кейс:

У тебя табы или роуты, и ты хочешь, чтобы при переключении вкладки не терялись вводимые данные, скролл и т.д.
<KeepAlive>
<component :is="currentTabComponent" />
</KeepAlive>


А если я хочу контролировать, что именно кешируется?

У KeepAlive в Vue 2.1.0+ есть пропсы include и exclude, туда можно вписать имена компонентов:
<!-- строка, разделённая запятыми -->
<KeepAlive include="a,b">
<component :is="view" />
</KeepAlive>

<!-- регулярное выражение (используйте `v-bind`) -->
<KeepAlive :include="/a|b/">
<component :is="view" />
</KeepAlive>

<!-- массив (используйте `v-bind`) -->
<KeepAlive :include="['a', 'b']">
<component :is="view" />
</KeepAlive>


А ещё можно использовать max, чтобы указать, сколько компонентов максимум можно держать в памяти.
<KeepAlive :max="2">
<component :is="currentTabComponent" />
</KeepAlive>


Что нового во
Vue 3?
Раньше было просто: компонент либо кешировался, либо нет. А теперь у нас больше гибкости:

Новое поведение: onActivated и onDeactivated

Когда компонент попадает в KeepAlive, Vue не вызывает unmounted, как обычно. Вместо этого срабатывают хуки:
onActivated(() => {
console.log('Я снова в деле!');
});

onDeactivated(() => {
console.log('Пошёл отдыхать');
});


Это значит, что ты можешь спокойно ставить на паузу таймеры, отписываться от чего-то тяжёлого, останавливать анимации и т.д.

Когда не надо использовать?
— Если компонент дешёвый (рендерится быстро)
— Если тебе не важно сохранять состояние
— Если ты хочешь, чтобы он пересоздавался при каждом появлении

TL;DR:
— KeepAlive сохраняет компоненты в памяти
— Не вызывает unmounted, используй onActivated и onDeactivated
— Можно фильтровать компоненты через include / exclude
— Есть max — ограничитель памяти
— Работает только с одним дочерним компонентом (или <component>)

Ну и дока
RU: https://ru.vuejs.org/guide/built-ins/keep-alive
EN: https://vuejs.org/guide/built-ins/keep-alive.html
#vue

Сегодня поболтаем про onRenderTracked() и onRenderTriggered() — штуки, которые редко используют, но зря! 🔍

Что делают?
onRenderTracked — показывает, за чем Vue следит во время рендера (что "отслеживает").

onRenderTriggered — показывает, что изменилось и вызвало повторный рендер.

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

Пример использования

<script setup>
import { ref, onRenderTracked, onRenderTriggered } from 'vue';

const count = ref(0);
const name = ref('Vue');

onRenderTracked((e) => {
console.log('[tracked]', e);
});

onRenderTriggered((e) => {
console.log('[triggered]', e);
});
</script>

<template>
<div>
<p>Счётчик: {{ count }}</p>
<p>Имя: {{ name }}</p>
<button @click="count++">+1</button>
</div>
</template>


👉 Когда ты жмёшь кнопку, в консоль вылетит:
[triggered] { target: ..., key: "count", type: "set" }


Что приходит в этих хуках?

Vue кидает тебе объект с такими полями:
effect — ссылка на реактивный эффект (рендер)
target — объект, за которым следили/который сработал (ref, reactive и т.д.)
key — конкретное поле (count, name, и т.п.)
type — тип действия (get, set, add, delete, clear)
oldValue и newValue (в triggered) — что поменялось

А что полезного можно делать?

🔍 Диагностика “лишних” перерендеров
Допустим, у тебя компонент рендерится при изменении чего-то, что вообще не используется в шаблоне.
Пихаем onRenderTriggered, запускаем консоль и проверяем — если key не совпадает ни с чем в template, возможно, надо рефакторить.

🧪 Логирование зависимости
Можно даже накинуть табличку с console.table, чтобы красиво смотреть за чем следит твой компонент.
onRenderTracked((e) => {
console.table({
key: e.key,
type: e.type,
target: e.target
});
});


🎛 Анализ производительности
Можно повесить счётчик, сколько раз компонент триггерился. Если там десятки вызовов при одном клике — уже подозрительно.

TL;DR:
onRenderTracked = смотри, за чем следим
onRenderTriggered = смотри, что изменилось и вызвало ререндер
— Полезно для дебага и оптимизации
— Использовать только в dev-режиме

Ну и дока конечно тут:
https://ru.vuejs.org/api/composition-api-lifecycle.html#onrendertracked