Потеря реактивности и частые ошибки

↑ 4.1 Vue 3: основы, компоненты, Composition API · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

«Почему компонент не обновляется?» — ждут перечня типовых причин.

Объяснение

СитуацияПочему теряетсяРешение
Деструктуризация reactive: const { a } = stateполучаем примитивtoRefs(state) / toRef
Деструктуризация props (до 3.5)то жеtoRefs(props) или () => props.x; в 3.5 — реактивная деструктуризация
Замена всего reactive: state = {...}переменная указывает на другой объектObject.assign(state, next) или ref
Передача значения ref.value в composableкопияпередавать ref или геттер (toValue)
ref внутри обычного объектане разворачивается.value или reactive
Вынос реактивного в обычную переменную/классвне отслеживанияоставлять в реактивной структуре
watch(state.prop)не реактивный источникwatch(() => state.prop)
markRaw/toRawнамеренно отключеноиспользовать сознательно
Изменение вне Vue (сторонняя библиотека)Vue не знаетtriggerRef, копия/замена
ref в Map/Setограниченноиспользовать реактивные коллекции
Асинхронность после await в watchEffectзависимости не собираютсячитать до await
// Ошибка
const { count } = useCounter();   // count — число, если composable вернул reactive-объект
// Правильно: composable возвращает refs
function useCounter() { const count = ref(0); return { count, inc: () => count.value++ }; }
 
// Приём: принимать ref/геттер/значение
function useTitle(source: MaybeRefOrGetter<string>) { watchEffect(() => (document.title = toValue(source))); }

Другие типовые ошибки:

  • Мутация props (props.x = 1) — предупреждение; эмитить событие или использовать defineModel.
  • Отсутствие key в списках.
  • Тяжёлые вычисления в шаблоне, а не в computed.
  • Забытая очистка таймеров/слушателей.
  • Обращение к DOM до onMounted и без nextTick после изменения данных.
  • Реактивный объект с тяжёлыми не-реактивными данными (карты, инстансы) — markRaw.

Нюансы и подводные камни

  • Проверяйте isRef, isReactive, Vue DevTools (подсветка обновлений).
  • Разворачивание ref в шаблоне работает только для верхнего уровня.
  • Реактивность массива: методы push/splice и индексная запись работают во Vue 3.

Практика

  1. Воспроизведите 5 случаев потери реактивности и исправьте.
  2. Перепишите composable, принимающий MaybeRefOrGetter.
  3. Найдите мутацию props в своём проекте.

Вопросы с ответами

Связанные темы