v-if, v-else-if и v-else — директивы условного рендеринга во Vue. Они позволяют показывать или скрывать элементы в зависимости от условия, при этом элементы полностью добавляются или удаляются из DOM.
Ключевые аспекты
v-if — отрисовывает элемент, если условие истинно
v-else-if — дополнительное условие, проверяется если предыдущее ложно
v-else — отрисовывается, если все предыдущие условия ложны
Ленивость — элемент не создаётся, пока условие не станет истинным
Полное удаление — при false элемент полностью удаляется из DOM
Плюсы
Экономия ресурсов — элементы не существуют в DOM при false
Ленивая инициализация компонентов
Работает с <template> для группировки элементов
Чистый декларативный синтаксис
Минусы
Дороже при частом переключении (элемент пересоздаётся)
Требует соблюдения порядка директив (v-else сразу после v-if)
Нельзя комбинировать с v-for на одном элементе
Частые ошибки на собеседованиях
Путают v-if с v-show (v-show только скрывает через CSS display: none)
Не знают, что v-else должен идти сразу после v-if без промежуточных элементов
Забывают про <template v-if> для условного рендеринга группы элементов
Используют v-if там, где лучше подойдёт v-show для частого переключения
Введение и проблематика
В интерактивных приложениях часто нужно показывать разный контент в зависимости от состояния:
Форма авторизации или профиль пользователя
Сообщение об ошибке или успешный результат
Разные варианты интерфейса для разных ролей
Vue предоставляет директивы условного рендеринга для декларативного управления отображением элементов.
В отличие от v-show, директивы v-if полностью добавляют или удаляют элементы из DOM, а не просто скрывают их через CSS.
<template> <divv-if="isLoggedIn"> Добро пожаловать! </div> <divv-else> Пожалуйста, войдите в систему </div></template><scriptsetup>import { ref } from'vue'constisLoggedIn=ref(false)</script>
v-else-if — цепочка условий
vue
<template> <divv-if="status === 'loading'"> Загрузка... </div> <divv-else-if="status === 'error'"> Произошла ошибка </div> <divv-else-if="status === 'empty'"> Данные отсутствуют </div> <divv-else> {{ data }} </div></template><scriptsetup>import { ref } from'vue'conststatus=ref('success')constdata=ref('Контент загружен')</script>
Практические примеры
Условный рендеринг группы элементов
Используйте <template> для группировки без добавления лишнего элемента в DOM:
<template><!-- Элемент полностью удаляется из DOM --> <divv-if="isVisible"> Контент </div></template>
Элемент добавляется/удаляется из DOM
Ленивая инициализация
Подходит для редкого переключения
Работает с v-else и v-else-if
Пограничные кейсы
⚠️
Элемент с v-else или v-else-if должен идти непосредственно после элемента с v-if или v-else-if. Между ними не должно быть других элементов.
vue
<template><!-- ❌ Неправильно — между v-if и v-else есть другой элемент --> <divv-if="condition">A</div> <span>Разделитель</span> <divv-else>B</div><!-- ✅ Правильно --> <divv-if="condition">A</div> <divv-else>B</div></template>
🚫
Не используйте v-if и v-for на одном элементе. v-if имеет более высокий приоритет и не будет иметь доступа к переменным из v-for.
vue
<template><!-- ❌ Неправильно --> <liv-for="item in items"v-if="item.isActive"> {{ item.name }} </li><!-- ✅ Правильно — используйте computed или template --> <templatev-for="item in items" :key="item.id"> <liv-if="item.isActive"> {{ item.name }} </li> </template></template>
Ленивая инициализация
При v-if="false" компонент не создаётся до тех пор, пока условие не станет истинным:
v-if полностью удаляет элемент из DOM, v-show только скрывает через CSS display: none. v-if дороже при переключении, но экономит ресурсы когда элемент скрыт.
Q: Можно ли использовать v-if и v-for вместе?
Технически можно, но не рекомендуется. v-if имеет приоритет и не видит переменные из v-for. Используйте computed или оборачивайте в template.
Q: Что такое ленивая инициализация в контексте v-if?
Компонент внутри v-if не создаётся и не выполняет свой setup/mounted, пока условие не станет true. Это экономит ресурсы.
Q: Зачем нужен template с v-if?
Чтобы условно отрендерить группу элементов без добавления обёртки в DOM. Сам template не создаёт элемент.