Чем отличается v-if от v-show?

Во Vue.js v-if и v-show используются для условного отображения элементов, но работают они по-разному как логически, так и технически, и каждую директиву применяют в зависимости от контекста задачи.

Основное различие

Характеристика v-if v-show
Механизм Удаляет/добавляет элемент в DOM Просто прячет/показывает элемент через CSS (display: none)
--- --- ---
Начальная загрузка Не рендерит, пока условие false Рендерит всегда, но скрывает
--- --- ---
Производительность при переключениях Медленно, т.к. каждый раз монтирует/размонтирует Быстро, просто меняет стиль
--- --- ---
Затраты при первой отрисовке Быстрее, если условие false, т.к. элемент не создаётся Дольше, т.к. элемент рендерится всегда
--- --- ---
Использование Когда нужно условно создавать/удалять элементы Когда нужно часто показывать/скрывать без удаления
--- --- ---

Как работает v-if

v-if добавляет или удаляет элемент из DOM динамически. То есть при false элемент полностью исчезает из дерева DOM и Vue освобождает ресурсы (память, слушатели событий и т.д.).

<div v-if="isVisible">Контент</div>

Если isVisible = false, этого элемента вообще не будет в DOM. При true — он создаётся с нуля.

Это поведение особенно полезно, когда:

  • ты не хочешь, чтобы элемент загружался, пока не потребуется;

  • элемент тяжёлый и не нужен по умолчанию;

  • нужно инициировать заново каждый раз при отображении (например, загрузка данных, пересоздание компонента).

Также v-if поддерживает v-else и v-else-if:

&lt;p v-if="type === 'A'"&gt;Тип A&lt;/p&gt;
&lt;p v-else-if="type === 'B'"&gt;Тип B&lt;/p&gt;
&lt;p v-else&gt;Другой тип&lt;/p&gt;

Как работает v-show

v-show всегда рендерит элемент в DOM, но управляет его видимостью через стиль display.

<div v-show="isVisible">Контент</div>

Если isVisible = false, элемент по-прежнему в DOM, но ему будет назначен стиль display: none, поэтому он не видим, но остаётся в памяти и может занимать ресурсы (например, прослушка событий).

Такой подход полезен, если:

  • тебе нужно часто показывать/прятать элемент без его пересоздания;

  • важна скорость переключения видимости;

  • элемент содержит внутреннее состояние, которое должно сохраняться между скрытием и показом.

Под капотом

Пример 1 — v-if

&lt;template&gt;
&lt;button @click="toggle"&gt;Показать/Скрыть&lt;/button&gt;
&lt;div v-if="visible"&gt;Hello&lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
export default {
data() {
return {
visible: false
}
},
methods: {
toggle() {
this.visible = !this.visible
}
}
}
&lt;/script&gt;

Когда visible = false, элемент <div> даже не существует в DOM. Vue отмонтирует его полностью, включая все дочерние компоненты, события, реактивные привязки.

Пример 2 — v-show

&lt;template&gt;
&lt;button @click="toggle"&gt;Показать/Скрыть&lt;/button&gt;
&lt;div v-show="visible"&gt;Hello&lt;/div&gt;
&lt;/template&gt;

DOM всегда содержит этот <div>, но Vue просто переключает его стиль:

display: none;

Нет размонтирования, всё остаётся на месте, в том числе компоненты, слушатели, данные и т.д.

Когда использовать v-if

  • Элемент не должен загружаться, пока это не нужно.

  • Важно уменьшить нагрузку на DOM.

  • Нужно пересоздавать состояние при каждом отображении.

  • Тяжёлые компоненты, сетевые запросы, графики, табличные данные и пр.

Когда использовать v-show

  • Частое переключение отображения — кнопки, вкладки, модалки, тултипы.

  • Важна плавность отображения без потери состояния.

  • Компоненты лёгкие, нет смысла пересоздавать.

Примеры различий на практике

Диалоговое окно (часто показывается и скрывается):

&lt;Modal v-show="isOpen" /&gt;

→ Используем v-show, чтобы сохранить состояние и моментально показывать/прятать.

Панель, которая показывается только после действия:

&lt;Sidebar v-if="showSidebar" /&gt;

→ Используем v-if, потому что не хотим загружать компонент до клика.

Список, загружаемый с сервера:

&lt;ul v-if="items.length &gt; 0">
&lt;li v-for="item in items" :key="item.id"&gt;{{ item.name }}&lt;/li&gt;
&lt;/ul&gt;

→ v-if помогает избежать показа пустых списков и не рендерит ничего, пока items не загружены.

Комбинированное использование

Иногда используют v-if и v-show совместно:

&lt;template&gt;
&lt;Modal v-if="shouldMountModal" v-show="isModalVisible" /&gt;
&lt;/template&gt;
  • v-if="shouldMountModal" решает, будет ли вообще компонент создан.

  • v-show="isModalVisible" решает, будет ли он видим.

Такой подход применяется, например, в сложных компонентах, где инициализация тяжёлая, но после этого нужна быстрая смена видимости.

Vue и ключи при v-if

Если в списке переключаются элементы с v-if, важно использовать :key, иначе Vue может не пересоздать компонент корректно:

&lt;component :is="currentComponent" :key="currentComponent" /&gt;

Без key Vue может переиспользовать компонент, что приведёт к багам.

v-if и v-show — это инструменты с разными задачами: v-if управляет существованием элемента, а v-show — его видимостью. Выбор между ними влияет на производительность, реактивность и пользовательский опыт.