Условный вывод: v-if и v-show
Условный вывод — показ элемента только тогда, когда выполнено условие. В списке задач это сообщение «Задач нет» для пустого списка или поздравление, когда всё выполнено.
Директива v-if
<!-- src/App.vue -->
<script setup>
import { ref } from 'vue'
const todos = ref([])
</script>
<template>
<h1>Мои задачи</h1>
<p v-if="todos.length === 0">Задач пока нет.</p>
</template>Под заголовком появится «Задач пока нет.». Когда в массиве появится хотя бы одна задача, абзац исчезнет из страницы — Vue удалит его из DOM.
v-else и v-else-if
Альтернативные ветки ставят сразу после элемента с v-if:
<script setup>
import { ref, computed } from 'vue'
const todos = ref([
{ id: 1, text: 'Купить хлеб', done: true },
{ id: 2, text: 'Позвонить Анне', done: false },
])
const remaining = computed(() => todos.value.filter((t) => !t.done).length)
</script>
<template>
<p v-if="todos.length === 0">Задач пока нет.</p>
<p v-else-if="remaining === 0">Всё выполнено!</p>
<p v-else>Осталось задач: {{ remaining }}</p>
</template>Сейчас страница покажет «Осталось задач: 1». Vue проверяет условия сверху вниз и выводит только первую подходящую ветку.
Группа элементов
Чтобы показать по условию несколько элементов без лишней обёртки, используют тег template — сам он на страницу не попадает:
<template>
<template v-if="todos.length > 0">
<h2>Список</h2>
<p>Нажмите на задачу, чтобы отметить её.</p>
</template>
</template>Заголовок и абзац появятся вместе, когда список не пуст.
Директива v-show
v-show тоже скрывает элемент, но по-другому: элемент всегда остаётся в DOM, Vue только переключает ему стиль display: none.
<script setup>
import { ref } from 'vue'
const showHelp = ref(false)
</script>
<template>
<button @click="showHelp = !showHelp">Справка</button>
<p v-show="showHelp">Введите текст задачи и нажмите Enter.</p>
</template>Кнопка открывает и закрывает подсказку. В инструментах разработчика видно, что абзац есть на странице всегда, меняется только его стиль.
Что выбрать
v-if | v-show | |
|---|---|---|
| Скрытый элемент | Удаляется из DOM | Остаётся, display: none |
| Начальная отрисовка | Дешевле, если условие ложно | Элемент рисуется всегда |
| Частое переключение | Дороже | Дешевле |
Работает с v-else и template | Да | Нет |
Если элемент переключают часто — меню, подсказка, вкладки, — берите v-show. Если условие меняется редко или элемент тяжёлый — v-if.
Частая ошибка
Между v-if и v-else не должно быть других элементов:
<template>
<p v-if="todos.length === 0">Задач пока нет.</p>
<hr>
<p v-else>Список задач</p>
</template>Vue не найдёт пару для v-else и выведет ошибку компиляции. Ставьте ветки строго одну за другой.