Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як у Vue 3.5 деструктурувати props без втрати реактивності і як за ними спостерігати?

До Vue 3.5 деструктуризація props губила реактивність: const { title } = defineProps(...) давала звичайне значення на момент створення компонента.

З Vue 3.5 деструктуризація з defineProps реактивна:

<script setup>
const { title, count = 0 } = defineProps(['title', 'count']);
</script>

<template>
  <h1>{{ title }}</h1>
  <p>{{ count }}</p>
</template>

Компілятор <script setup> переписує звернення title на __props.title, тож значення завжди актуальне. Заодно це найзручніший спосіб задати значення за замовчуванням - звичайним синтаксисом JavaScript замість withDefaults.

Пастка - передача у функцію чи watch:

const { id } = defineProps(['id']);

watch(id, () => { /* ... */ });          // помилка компіляції: передано значення, а не джерело
watch(() => id, () => { /* ... */ });    // правильно: геттер

useFetch(id);                            // composable отримає число, а не реактивне джерело
useFetch(() => id);                      // правильно

Деструктуризована змінна виглядає як звичайна змінна, але реактивна лише там, де компілятор може переписати звернення. Передаючи її кудись, треба загорнути в геттер, - інакше функція отримає «знімок» значення.

Спостереження за props без деструктуризації:

const props = defineProps(['id', 'filters']);

watch(() => props.id, (id) => load(id));
watch(() => props.filters, reload, { deep: true });   // об'єкт - глибоко

watch(props.id, ...) - та сама помилка: значення замість джерела.

Що варто знати:

  • props змінювати не можна - вони належать батьківському компоненту. Для локальної копії - ref(props.initial) (свідомо не реактивна до змін батька) або computed;
  • об'єкти в props передаються за посиланням, і зміна їх полів технічно спрацює, але порушує односпрямований потік даних - батько не знатиме, хто змінив його стан;
  • для v-model на компоненті - defineModel(), а не зміна props.

Докладніше в документації: Реактивна деструктуризація props

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання