Интервью-вопрос
Как навязывается реактивность во Vue 3
Во Vue 3 данные становятся реактивными, когда вы явно создаете реактивный источник через ref, reactive, computed или related API. На практике важно понимать Proxy, .value, отслеживание зависимостей и места, где связь с реактивностью легко потерять.
- Добавлен
- Редакция
Подготовьте короткий ответ и пару деталей на случай уточняющих вопросов.
Мини-квиз
Проверка перед разбором
Несколько быстрых вопросов перед разбором. Так проще поймать места, которые только кажутся понятными.
Вопрос 1 из 50 правильно
Разбор
Разобраться, а не зазубрить
Дальше разбираем суть, типичные уточнения и места, где легко сказать лишнее или перепутать термины.
Базовая идея
Во Vue 3 реактивность не появляется у любой переменной автоматически. Вы создаете реактивный источник через ref, reactive, computed и другие API. После этого Vue может отслеживать, кто прочитал значение, и кого нужно обновить при изменении.
Для объектов основа механизма это Proxy. Proxy перехватывает операции вроде чтения свойства, записи нового значения, удаления поля и работы с коллекциями. Поэтому Vue видит не только "что значение изменилось", но и какой ключ был затронут.
Для примитивов Proxy напрямую не подходит, потому что примитив нельзя обернуть как объект с перехватом свойств. Поэтому ref(0) возвращает объект-обертку, а само число лежит в count.value.
Как это звучит на интервью
Хороший короткий ответ можно построить в три шага.
- Назвать источник реактивности:
refиreactive. - Объяснить механизм: Proxy для объектов и
.valueдля ref. - Добавить практический риск: потеря реактивности при деструктуризации, забытая
.value, лишняя глубокая реактивность.
Пример ответа:
Во Vue 3 реактивность появляется, когда состояние создается через ref, reactive или похожие API. reactive возвращает Proxy вокруг объекта и перехватывает чтение и запись свойств. ref нужен в том числе для примитивов и хранит значение в .value. Когда render, computed или watchEffect читает реактивное значение, Vue запоминает зависимость и потом обновляет только связанные эффекты.
Такой ответ показывает и механизм, и практику. Он лучше, чем фраза "Vue сам все отслеживает", потому что сразу видно, где границы автоматизации.
Как выбрать ref, reactive и соседние API
На интервью не обязательно спорить, что всегда лучше. Важно показать критерий выбора. ref удобен для одного значения и для состояния, которое заменяется целиком. reactive удобен для связанного объекта, например формы или локального состояния с несколькими полями.
Если вы передаете отдельное поле reactive-объекта в composable, обычная деструктуризация может сломать связь. В таком случае используйте toRef или toRefs. Если объект тяжелый или пришел из внешней библиотеки, не включайте глубокую реактивность без причины.
Как выбрать реактивный API
Берите ref и меняйте значение через .value в JavaScript-коде.Берите reactive, но не теряйте связь через обычную деструктуризацию.Используйте toRef или toRefs, чтобы сохранить реактивную ссылку.Проверьте shallowRef, shallowReactive или markRaw, чтобы не создавать лишнюю реактивность.Что именно отслеживает Vue
Vue отслеживает зависимости во время выполнения активного эффекта. Активным эффектом может быть render компонента, getter computed или функция внутри watchEffect. Если во время выполнения было прочитано state.user.name, Vue связывает этот эффект с конкретным реактивным ключом.
Это важно для ответа на вопрос про "автоматическое" обновление. Автоматическое не значит "после любого изменения пересчитать все". Vue обновляет то, что связано с прочитанными реактивными данными. Если значение не было прочитано внутри эффекта, зависимости не возникнет.
- 1Компонент, computed или watchEffect начинает выполняться.
- 2Код читает ref.value или свойство reactive-объекта.
- 3Vue связывает активный эффект с прочитанным ключом.
- 4Следующее изменение этого ключа сможет запланировать обновление.
- 1Код присваивает новое значение через ref.value или свойство Proxy.
- 2Vue сравнивает изменение и находит зависимые эффекты.
- 3Обновления ставятся в очередь, а не выполняются хаотично в каждой строке.
- 4UI получает новое состояние на следующем цикле обновления.
Практический пример с ref и reactive
В этом примере есть и примитив через ref, и объект через reactive.
<script setup>
import { computed, reactive, ref, toRefs } from 'vue'
const count = ref(0)
const form = reactive({
name: '',
accepted: false,
})
const { name } = toRefs(form)
const canSubmit = computed(() => {
return name.value.trim().length > 0 && form.accepted
})
function increment() {
count.value += 1
}
</script>count это ref, поэтому в increment нужна запись через count.value. form это Proxy, поэтому form.accepted остается реактивным при чтении. Поле name вынесено через toRefs, поэтому оно не потеряло связь с form.name.
Плохой вариант:
const form = reactive({ name: '', accepted: false })
const { name } = formТак вы получаете обычное значение name на момент деструктуризации. Если потом изменится form.name, отдельная переменная может не обновиться как реактивная ссылка. Безопасная замена: const { name } = toRefs(form) или чтение form.name напрямую.
ref в шаблоне и ref в JavaScript
Важный нюанс для интервью: Vue часто автоматически разворачивает ref в шаблоне, поэтому можно писать проще. Но это не отменяет .value в JavaScript-коде.
<script setup>
import { ref } from 'vue'
const count = ref(0)
function add() {
count.value += 1
}
</script>
<template>
<button @click="add">{{ count }}</button>
</template>В шаблоне {{ count }} показывает значение, а не сам объект ref. В функции add нужно менять count.value. Если сказать "ref разворачивается всегда", интервьюер легко поймает это уточняющим вопросом про script.
Практический вывод
Смысл ответа не в том, чтобы перечислить все API Vue. Нужно показать, что вы понимаете контракт реактивности: состояние должно быть реактивным источником, чтение создает зависимость, запись триггерит связанные обновления.
Для frontend-кода из этого следуют простые правила. Не храните состояние UI в обычных локальных переменных, если от него должен обновляться шаблон. Не вытаскивайте поля reactive-объекта обычной деструктуризацией, если нужна связь. Не делайте глубоким реактивным то, что не должно участвовать в рендере, например тяжелый внешний инстанс.
Если ответить так, вы покажете не только знание Vue 3, но и способность избежать реальных багов: неработающей кнопки, зависшего computed, лишнего перерендера или сломанной формы.
Частые ошибки
Где обычно ошибаются
Проверьте формулировки, которые звучат уверенно, но на интервью быстро выдают пробелы.
- 1
Говорить, что Vue делает реактивным весь JavaScript
Vue не перехватывает обычные локальные переменные. Если написатьlet count = 0, шаблон не начнет обновляться только из-за изменения этой переменной. Для состояния компонента нужно использоватьref,reactiveили другой реактивный источник. - 2
Забывать .value у ref
Вscriptзначение ref читается и меняется через.value. Если сравнить сам ref с числом или строкой, условие будет работать не так, как вы ожидаете. В ответе лучше отдельно сказать, что шаблон разворачивает ref удобнее, но JavaScript-код остается явным. - 3
Деструктурировать reactive как обычный объект
Конструкцияconst { count } = stateзабирает значение поля и может оторвать его от Proxy. Потом изменениеstate.countне обязательно обновит переменнуюcount. Безопаснее читатьstate.countнапрямую или использоватьtoRefs(state). - 4
Путать computed и watch
computedнужен для производного значения и должен оставаться предсказуемым getter.watchчаще используют для побочных эффектов, например запроса, синхронизации или работы с внешним API. Если смешать роли, можно получить лишние запросы, сложный lifecycle и неожиданные обновления. - 5
Делать реактивным все подряд
Не каждый объект должен становиться глубоким Proxy. Для больших неизменяемых структур, инстансов библиотек и внешних объектов глубокая реактивность может добавить лишнюю стоимость и сложные баги. В таких местах стоит рассмотретьshallowRef,markRawили хранить только нужные простые данные.
Follow-up
Что могут спросить дальше
Короткие ответы на вопросы, которыми проверяют понимание реактивности Vue 3.
Живые ответы
Видео с похожим вопросом
Если найдем публичные интервью с таким вопросом, добавим их сюда. Их удобно смотреть после теории, чтобы свериться с живыми ответами.
Пока видео нет. Когда появятся подходящие публичные интервью, добавим их в этот блок, чтобы можно было сравнить разбор с тем, как отвечают реальные кандидаты.
Есть ли опыт работы с Angular 😎
Отвечайте честно про глубину опыта с Angular: коммерческий проект, пет-проект, поддержка legacy или только знакомство. На странице разбираем, как показать уровень без преувеличений и какие технические детали стоит упомянуть.
Как построена реактивность во Vue3 😎
Реактивность во Vue3 строится на Proxy для объектов, ref для значений и системе track/trigger для зависимостей. Разбираем, что сказать на интервью и какие ловушки встречаются в реальном frontend-коде.