Vue Front-end Инженер

Vue Front-end Инженер

Роадмап навыков для прокачки

Условный рендеринг: v-if, v-else-if, v-else

VueJSTemplate SyntaxДирективы

Основная идея

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.


Базовая теория

v-if — базовое условие

vue
<template>
  <div v-if="isLoggedIn">
    Добро пожаловать, {{ username }}!
  </div>
</template>
 
<script setup>
import { ref } from 'vue'
 
const isLoggedIn = ref(true)
const username = ref('Иван')
</script>

v-else — альтернативный блок

vue
<template>
  <div v-if="isLoggedIn">
    Добро пожаловать!
  </div>
  <div v-else>
    Пожалуйста, войдите в систему
  </div>
</template>
 
<script setup>
import { ref } from 'vue'
 
const isLoggedIn = ref(false)
</script>

v-else-if — цепочка условий

vue
<template>
  <div v-if="status === 'loading'">
    Загрузка...
  </div>
  <div v-else-if="status === 'error'">
    Произошла ошибка
  </div>
  <div v-else-if="status === 'empty'">
    Данные отсутствуют
  </div>
  <div v-else>
    {{ data }}
  </div>
</template>
 
<script setup>
import { ref } from 'vue'
 
const status = ref('success')
const data = ref('Контент загружен')
</script>

Практические примеры

Условный рендеринг группы элементов

Используйте <template> для группировки без добавления лишнего элемента в DOM:

vue
<template>
  <template v-if="showDetails">
    <h2>Заголовок</h2>
    <p>Описание</p>
    <span>Дополнительная информация</span>
  </template>
</template>
 
<script setup>
import { ref } from 'vue'
 
const showDetails = ref(true)
</script>

Авторизация и роли

vue
<template>
  <nav>
    <a href="/">Главная</a>
 
    <template v-if="user">
      <a href="/profile">Профиль</a>
      <a v-if="user.role === 'admin'" href="/admin">
        Админ-панель
      </a>
      <button @click="logout">Выйти</button>
    </template>
 
    <template v-else>
      <a href="/login">Войти</a>
      <a href="/register">Регистрация</a>
    </template>
  </nav>
</template>
 
<script setup>
import { ref } from 'vue'
 
const user = ref({ name: 'Админ', role: 'admin' })
 
function logout() {
  user.value = null
}
</script>

v-if vs v-show

vue
<template>
  <!-- Элемент полностью удаляется из DOM -->
  <div v-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 есть другой элемент -->
  <div v-if="condition">A</div>
  <span>Разделитель</span>
  <div v-else>B</div>
 
  <!-- ✅ Правильно -->
  <div v-if="condition">A</div>
  <div v-else>B</div>
</template>
🚫

Не используйте v-if и v-for на одном элементе. v-if имеет более высокий приоритет и не будет иметь доступа к переменным из v-for.

vue
<template>
  <!-- ❌ Неправильно -->
  <li v-for="item in items" v-if="item.isActive">
    {{ item.name }}
  </li>
 
  <!-- ✅ Правильно — используйте computed или template -->
  <template v-for="item in items" :key="item.id">
    <li v-if="item.isActive">
      {{ item.name }}
    </li>
  </template>
</template>

Ленивая инициализация

При v-if="false" компонент не создаётся до тех пор, пока условие не станет истинным:

vue
<template>
  <button @click="showHeavyComponent = true">
    Загрузить компонент
  </button>
 
  <!-- HeavyComponent не инициализируется до клика -->
  <HeavyComponent v-if="showHeavyComponent" />
</template>
 
<script setup>
import { ref } from 'vue'
import HeavyComponent from './HeavyComponent.vue'
 
const showHeavyComponent = ref(false)
</script>

Плюсы и минусы

Аспектv-ifv-show
DOMДобавляет/удаляетВсегда присутствует
ИнициализацияЛениваяНемедленная
ПереключениеДорожеДешевле
SSRРаботаетРаботает
<template>ПоддерживаетНе поддерживает
v-elseПоддерживаетНе поддерживает

Когда использовать:

  • v-if — условие редко меняется, нужна ленивая инициализация
  • v-show — частое переключение видимости (tabs, модалки)

Вопросы интервьюера

Q: В чём разница между v-if и v-show?

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 не создаёт элемент.


Источники