Директива v-if полностью **добавляет или удаляет элемент из DOM** в зависимости от условия. Когда условие ложно, элемент не существует в DOM вообще.
<template>
<div v-if="isLoggedIn">
<p>Добро пожаловать, {{ username }}!</p>
<button @click="logout">Выйти</button>
</div>
</template>
<script setup>
const isLoggedIn = ref(false)
const username = ref('Алексей')
</script>Работает аналогично обычным условным операторам JavaScript:
<template>
<p v-if="score >= 90">Отлично!</p>
<p v-else-if="score >= 70">Хорошо</p>
<p v-else-if="score >= 50">Удовлетворительно</p>
<p v-else">Нужно подтянуть знания</p>
</template>Важно: v-else-if и v-else должны идти **сразу после** элемента с v-if — без других элементов между ними.
Если нужно условно скрыть группу элементов без обёртки в лишний <div>, используется тег <template> — он не рендерится в DOM:
<template v-if="isAdmin">
<h2>Панель администратора</h2>
<p>Здесь управление пользователями</p>
<AdminTable />
</template>Директива v-show работает иначе: элемент **всегда находится в DOM**, но при ложном условии к нему применяется display: none:
<template>
<div v-show="isVisible">
Этот блок скрыт через display: none
</div>
</template>
<script setup>
const isVisible = ref(true)
</script>| Характеристика | v-if | v-show |
|---|---|---|
| Элемент в DOM при false | Нет (удалён) | Да (display: none) |
| Стоимость переключения | Высокая (пересоздание) | Низкая (CSS) |
| Стоимость первого рендера | Низкая (если false) | Высокая (всегда рендерится) |
| Поддержка v-else | Да | Нет |
| Поддержка <template> | Да | Нет |
**Когда использовать v-show:** когда элемент часто переключается (например, выпадающее меню, модальное окно которое открывают/закрывают много раз).
**Когда использовать v-if:** когда условие редко меняется, или при false рендеринг элемента не нужен вообще (например, панель администратора, которую видит лишь малый процент пользователей).
Если v-if изначально равно false, Vue вообще не рендерит элемент — не создаёт компонент, не запускает его хуки жизненного цикла. Это важно при работе с тяжёлыми компонентами:
<!-- HeavyChart создастся только когда showChart = true -->
<HeavyChart v-if="showChart" :data="chartData" />С v-show компонент создастся при первом рендере страницы, даже если он скрыт.
Эмуляция v-if и v-show: разница между удалением из DOM и скрытием через display:none
// Сравниваем поведение v-if (удаление из DOM) и v-show (display: none)
// Псевдо-DOM для демонстрации
class PseudoDOM {
constructor() {
this.elements = new Map()
this.parent = { children: [] }
}
createElement(tag, id) {
const el = { tag, id, style: {}, inDOM: false }
this.elements.set(id, el)
return el
}
// v-if: добавляем/удаляем элемент из DOM
vIf(el, condition) {
if (condition && !el.inDOM) {
this.parent.children.push(el)
el.inDOM = true
console.log(`[v-if] <${el.tag}#${el.id}> ДОБАВЛЕН в DOM`)
} else if (!condition && el.inDOM) {
this.parent.children = this.parent.children.filter(c => c !== el)
el.inDOM = false
console.log(`[v-if] <${el.tag}#${el.id}> УДАЛЁН из DOM`)
} else {
console.log(`[v-if] <${el.tag}#${el.id}> без изменений (condition=${condition})`)
}
}
// v-show: меняем только display
vShow(el, condition) {
if (!el.inDOM) {
this.parent.children.push(el)
el.inDOM = true
}
el.style.display = condition ? '' : 'none'
console.log(`[v-show] <${el.tag}#${el.id}> display="${el.style.display || 'block'}" (в DOM: да)`)
}
printDOM() {
console.log('\nТекущее состояние DOM:')
if (this.parent.children.length === 0) {
console.log(' (пусто)')
}
this.parent.children.forEach(el => {
const display = el.style.display === 'none' ? ' [скрыт: display:none]' : ''
console.log(` <${el.tag} id="${el.id}"${display}>`)
})
}
}
const dom = new PseudoDOM()
const panel = dom.createElement('div', 'admin-panel')
const menu = dom.createElement('nav', 'dropdown-menu')
console.log('=== v-if: переключаем панель администратора ===')
dom.vIf(panel, false) // изначально скрыт — в DOM нет вообще
dom.printDOM()
dom.vIf(panel, true) // пользователь вошёл как админ
dom.printDOM()
dom.vIf(panel, false) // вышел из аккаунта
dom.printDOM()
console.log('\n=== v-show: переключаем выпадающее меню ===')
dom.vShow(menu, false) // закрыто, но в DOM присутствует
dom.printDOM()
dom.vShow(menu, true) // открыто
dom.printDOM()
dom.vShow(menu, false) // снова закрыто — просто display:none
dom.printDOM()
console.log('\n=== Вывод ===')
console.log('v-if: дорогое создание/удаление, идеально для редко меняющихся условий')
console.log('v-show: дешёвое переключение, идеально для частых переключений')Директива v-if полностью **добавляет или удаляет элемент из DOM** в зависимости от условия. Когда условие ложно, элемент не существует в DOM вообще.
<template>
<div v-if="isLoggedIn">
<p>Добро пожаловать, {{ username }}!</p>
<button @click="logout">Выйти</button>
</div>
</template>
<script setup>
const isLoggedIn = ref(false)
const username = ref('Алексей')
</script>Работает аналогично обычным условным операторам JavaScript:
<template>
<p v-if="score >= 90">Отлично!</p>
<p v-else-if="score >= 70">Хорошо</p>
<p v-else-if="score >= 50">Удовлетворительно</p>
<p v-else">Нужно подтянуть знания</p>
</template>Важно: v-else-if и v-else должны идти **сразу после** элемента с v-if — без других элементов между ними.
Если нужно условно скрыть группу элементов без обёртки в лишний <div>, используется тег <template> — он не рендерится в DOM:
<template v-if="isAdmin">
<h2>Панель администратора</h2>
<p>Здесь управление пользователями</p>
<AdminTable />
</template>Директива v-show работает иначе: элемент **всегда находится в DOM**, но при ложном условии к нему применяется display: none:
<template>
<div v-show="isVisible">
Этот блок скрыт через display: none
</div>
</template>
<script setup>
const isVisible = ref(true)
</script>| Характеристика | v-if | v-show |
|---|---|---|
| Элемент в DOM при false | Нет (удалён) | Да (display: none) |
| Стоимость переключения | Высокая (пересоздание) | Низкая (CSS) |
| Стоимость первого рендера | Низкая (если false) | Высокая (всегда рендерится) |
| Поддержка v-else | Да | Нет |
| Поддержка <template> | Да | Нет |
**Когда использовать v-show:** когда элемент часто переключается (например, выпадающее меню, модальное окно которое открывают/закрывают много раз).
**Когда использовать v-if:** когда условие редко меняется, или при false рендеринг элемента не нужен вообще (например, панель администратора, которую видит лишь малый процент пользователей).
Если v-if изначально равно false, Vue вообще не рендерит элемент — не создаёт компонент, не запускает его хуки жизненного цикла. Это важно при работе с тяжёлыми компонентами:
<!-- HeavyChart создастся только когда showChart = true -->
<HeavyChart v-if="showChart" :data="chartData" />С v-show компонент создастся при первом рендере страницы, даже если он скрыт.
Эмуляция v-if и v-show: разница между удалением из DOM и скрытием через display:none
// Сравниваем поведение v-if (удаление из DOM) и v-show (display: none)
// Псевдо-DOM для демонстрации
class PseudoDOM {
constructor() {
this.elements = new Map()
this.parent = { children: [] }
}
createElement(tag, id) {
const el = { tag, id, style: {}, inDOM: false }
this.elements.set(id, el)
return el
}
// v-if: добавляем/удаляем элемент из DOM
vIf(el, condition) {
if (condition && !el.inDOM) {
this.parent.children.push(el)
el.inDOM = true
console.log(`[v-if] <${el.tag}#${el.id}> ДОБАВЛЕН в DOM`)
} else if (!condition && el.inDOM) {
this.parent.children = this.parent.children.filter(c => c !== el)
el.inDOM = false
console.log(`[v-if] <${el.tag}#${el.id}> УДАЛЁН из DOM`)
} else {
console.log(`[v-if] <${el.tag}#${el.id}> без изменений (condition=${condition})`)
}
}
// v-show: меняем только display
vShow(el, condition) {
if (!el.inDOM) {
this.parent.children.push(el)
el.inDOM = true
}
el.style.display = condition ? '' : 'none'
console.log(`[v-show] <${el.tag}#${el.id}> display="${el.style.display || 'block'}" (в DOM: да)`)
}
printDOM() {
console.log('\nТекущее состояние DOM:')
if (this.parent.children.length === 0) {
console.log(' (пусто)')
}
this.parent.children.forEach(el => {
const display = el.style.display === 'none' ? ' [скрыт: display:none]' : ''
console.log(` <${el.tag} id="${el.id}"${display}>`)
})
}
}
const dom = new PseudoDOM()
const panel = dom.createElement('div', 'admin-panel')
const menu = dom.createElement('nav', 'dropdown-menu')
console.log('=== v-if: переключаем панель администратора ===')
dom.vIf(panel, false) // изначально скрыт — в DOM нет вообще
dom.printDOM()
dom.vIf(panel, true) // пользователь вошёл как админ
dom.printDOM()
dom.vIf(panel, false) // вышел из аккаунта
dom.printDOM()
console.log('\n=== v-show: переключаем выпадающее меню ===')
dom.vShow(menu, false) // закрыто, но в DOM присутствует
dom.printDOM()
dom.vShow(menu, true) // открыто
dom.printDOM()
dom.vShow(menu, false) // снова закрыто — просто display:none
dom.printDOM()
console.log('\n=== Вывод ===')
console.log('v-if: дорогое создание/удаление, идеально для редко меняющихся условий')
console.log('v-show: дешёвое переключение, идеально для частых переключений')Напиши функцию `getVisibilityStrategy(frequency, initiallyVisible)`, которая возвращает строку `"v-if"` или `"v-show"`. Если элемент переключается часто (`frequency === "high"`) — используй `"v-show"`. Если редко (`frequency === "low"`) и изначально не виден (`initiallyVisible === false`) — используй `"v-if"`. В остальных случаях возвращай `"v-if"`.
Используй цепочку if/else: сначала проверь frequency === "high", затем остальные условия.
Токены для AI-помощника закончились
Купи токены чтобы задавать вопросы AI прямо в уроке