Vue.js Feed — Канал русскоговорящего сообщества
175 subscribers
3 photos
30 links
Канал Vue.js русскоговорящего сообщества: @vuejs_ru
加入频道
Vue 3.5 alpha.1 - Reactive Props Destructure
#vue_3_5 #changelog

Начали выходить alpha и beta версии нового Vue 🎉

Первое обновление - Reactive Props Destructure теперь доступен без экспериментального флага. Позволяет более красиво описывать значения по умолчанию в SFC Setup + TS.

RFC был спорный и долго горячо обсуждался. При компиляции обращение к переменой превращается в обращение к полю объекта.

Обсуждался ещё с 3.2 и был ранее добавлен под экспериментальным флагом в 3.3.

<script setup lang="ts">
// Before
const props = withDefaults(defineProps<
foo?: string
>(), {
foo: 'foo'
})

// After
const { foo = 'foo' } = defineProps<
foo?: string
>()

// foo <==> props.foo
</script>


- RFC: https://github.com/vuejs/rfcs/discussions/502
👍6👎2🔥2😢1
Vue 3.5.0-alpha.3 - Появился новый компосабл useId() для генерации ID в компонентах.
#vue_3_5 #changelog

const inputId = useId()


Зачем генерировать ID?

Типичный use-case - id элементов, например, форм и атрибуты для доступности.

Почему не просто `Math.random()` или `nanoid()`?

Результат получается невоспроизводимым, что усложняет тестирование и не работает на SSR

Почему не просто `id++`?

Такое решение может приводить к дублированию ID. Например, и в вашем приложении, и в UI фреймворке могли сделать input-label-${id++}.

Чтобы облегчить жизнь разработчиков, добавили долгожданный useId, возвращающий уникальный ID, префикс которого можно настроить в конфиге Vue приложения.

const app = createApp(App)
app.config.idPrefix = 'my-app'
// useId() === "my-app:0"


- PR: https://github.com/vuejs/core/pull/11404/
👍9🔥53🤔1🎉1🕊1🌚1
Vue 3.5.0-alpha.3: появился useTemplateRef(key) для Template Ref
#vue_3_5 #changelog

Позволяет описывать свойства для Template Ref аналогично ref(). Отличия:
- Семантически понятнее - явно определяется как переменная для template ref
- readonly - нельзя случайно изменить вручную
- Значение атрибута ref - определяемый отдельно ключ, а не имя переменной (свойства компонента)
- Возможно, будет особая поддержка в IDE ?

<script setup lang="ts">
// Vue 3.5+
const inputElement = useTemplateRef<HTMLInputElement>('inputElement')
// Или с отдельным ключом
const fileInputKey = 'FILE_INPUT'
const fileInputElement = useTemplateRef<HTMLInputElement>(fileInputKey)

// Аналог в прошлых версиях
const inputElement = ref<HTMLInputElement|null>()
</script>

<template>
<input ref="inputElement" />
<input :ref="fileInputKey" type="file" />
</template>


- Commit: https://github.com/vuejs/core/commit/3ba70e49b5856c53611c314d4855d679a546a7df
👍8🤔8🔥5
Vue 3.5: появился отдельный API для работы с cleanup-функциями в watch/watchEffect - onWatcherCleanup:

- позволяет зарегистрировать функцию “очищения”, которая будет вызываться прямо перед повторным запуском watch/watchEffect (например, если изменилась зависимость и он вот-вот сработает);

- подходит для того, чтобы, например, отменять асинхронные запросы (избегая гонки состояний) или очищать старые таймеры перед запуском новых;

- сильно облегчает работу в паре с watch: сейчас функция onCleanup передается в него третьим аргументом (после value и oldValue), что довольно неудобно, особенно, если первые 2 аргумента не нужны, поэтому раньше приходилось писать (_, __, onCleanup);

- имеет те же ограничения, что и остальные функции, привязанные к контексту выполнения - должен выполняться синхронно и вызываться внутри watch/watchEffect;

- дополнительно имеет второй аргумент failSilently, куда можно передать true, чтобы не получать предупреждение в консоли, если функция вызвана за пределами watch/watchEffect, что открывает окно для следующих паттернов:


export function request() {
const controller = new AbortController();

// регистрируем cleanup-функцию и передаем failSilently: true
onWatcherCleanup(() => controller.abort(), true);

return fetch(…, { signal: controller.signal });
}


либо можно воспользоваться еще одной новой функцией getCurrentWatcher и переписать код выше иначе:

export function request() {
const controller = new AbortController();

// если мы внутри вотчера
if (getCurrentWatcher()) {
// то регистрирурем cleanup-функцию
onWatcherCleanup(() => controller.abort());
}

return fetch(…, { signal: controller.signal });
}

тогда cleanup-функция будет зарегистрирована только в том случае, если мы находимся внутри watch/watchEffect.

Использование:

watchEffect(async () => {
const response = await request(…);
});


Новый подраздел в документации: https://vuejs.org/guide/essentials/watchers.html#side-effect-cleanup

PR: https://github.com/vuejs/core/pull/9927

#vue_3_5 #changelog
🔥15🤔2👍1