В чём разница между v-if, v-else-if, v-else и v-show?
v-if полностью добавляет/удаляет элемент из DOM, v-show только переключает display: none. v-if дешевле при частом отсутствии элемента, v-show — при частых переключениях видимости.
v-if: условный рендеринг
Директива v-if полностью монтирует и размонтирует компонент/элемент. При false элемент отсутствует в DOM.
<template>
<div v-if="isLoggedIn">
<UserProfile />
</div>
<div v-else>
<LoginForm />
</div>
</template>
При переходе false → true Vue создаёт элемент с нуля, запускает хуки onMounted, делает запросы данных. При true → false — вызывает onUnmounted, освобождает ресурсы.
v-else-if и v-else
Должны следовать непосредственно за v-if или v-else-if на соседнем элементе:
<p v-if="status === 'loading'">Загрузка...</p>
<p v-else-if="status === 'error'">Ошибка: {{ errorMsg }}</p>
<p v-else>Готово</p>
v-show: CSS-переключение
Директива v-show всегда рендерит элемент в DOM, управляя только инлайн-стилем display:
<div v-show="isMenuOpen">
<nav>...</nav>
</div>
<!-- Результат при false: <div style="display: none;">...</div> -->
Хуки жизненного цикла не вызываются при переключении v-show.
Когда что использовать
- v-if — когда элемент редко отображается (условие ложно большую часть времени) или несёт дорогостоящую инициализацию. Пример: блок для авторизованных пользователей.
- v-show — когда элемент часто переключается (dropdown-меню, аккордеон, tooltips). Первичная загрузка страницы дороже, но переключения мгновенны.
Использование с <template>
v-if можно применять к <template> — невидимой обёртке для нескольких элементов:
<template v-if="hasData">
<h2>Результаты</h2>
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
</template>
v-show не работает с <template> — применяйте только к реальным элементам.
Приоритет v-if vs v-for
В Vue 3 v-if имеет более высокий приоритет, чем v-for на одном элементе (в Vue 2 — наоборот). Не смешивайте их:
<!-- Плохо: v-if выполняется раньше v-for, item недоступен -->
<li v-for="item in list" v-if="item.active">{{ item.name }}</li>
<!-- Хорошо: фильтрация через computed -->
<li v-for="item in activeItems" :key="item.id">{{ item.name }}</li>
Подводные камни
v-showне работает с тегом<template>и с компонентами, у которыхdisplayпереопределён в CSS как!important.- Компоненты под
v-ifуничтожаются при скрытии — локальное состояние (введённые данные в форме) теряется. Используйтеv-showили выносите состояние выше. - Переход между
v-else-ветками с одинаковым тегом безkey— Vue переиспользует DOM-узел. Добавьтеkeyчтобы принудить пересоздание. - Тяжёлые компоненты под
v-showрендерятся при загрузке страницы даже если скрыты — это может замедлить LCP. Используйтеv-if+<Suspense>для отложенного рендера. - Смешение
v-ifиv-forна одном элементе — признанный антипаттерн; всегда разносите их по разным уровням.
Common mistakes
- Использовать
v-showдля одноразового условного блока, и зря держать DOM. - Использовать
v-ifдля часто мигающего тултипа. - Совмещать
v-ifиv-forна одном узле. - Считать, что
v-showулучшает SEO больше, чемv-if— для поисковика оба возвращают разметку, важна семантика.
What the interviewer is testing
- Понимает разницу «в DOM/нет в DOM».
- Знает, что
v-showнельзя применить к<template>. - Может назвать сценарии для каждого.
- Не путает поведение
v-else-ifс обычным if-else в шаблоне.