Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чому не можна ставити v-if і v-for на один елемент?

У Vue 3 на одному елементі v-if має вищий пріоритет, ніж v-for. Умова обчислюється раніше за цикл - і не має доступу до змінної циклу.

<!-- помилка: todo ще не визначено, коли перевіряється v-if -->
<li v-for="todo in todos" v-if="!todo.done">{{ todo.title }}</li>

У Vue 2 було навпаки (v-for першим), тож код, перенесений зі старих проєктів, ламається саме тут.

Правильні варіанти:

1. Фільтр - в обчислюваній властивості (найкращий варіант для фільтрації):

<script setup>
const activeTodos = computed(() => todos.value.filter((todo) => !todo.done));
</script>

<template>
  <li v-for="todo in activeTodos" :key="todo.id">{{ todo.title }}</li>
</template>

Фільтр виконується лише при зміні todos, а не на кожен рендер, і шаблон стає простішим.

2. <template> з v-for зовні, v-if усередині - коли умова для кожного елемента окрема:

<template v-for="todo in todos" :key="todo.id">
  <li v-if="!todo.done">{{ todo.title }}</li>
</template>

3. v-if зовні - для умови на весь список:

<ul v-if="todos.length">
  <li v-for="todo in todos" :key="todo.id">{{ todo.title }}</li>
</ul>
<p v-else>Завдань немає</p>

Що ще варто знати про v-for:

  • :key обов'язковий - стабільний ідентифікатор, а не індекс;
  • перебір об'єкта: v-for="(value, key, index) in object";
  • діапазон: v-for="n in 10" дає числа від 1 до 10;
  • на <template> key ставиться на сам <template>.

Чому computed краще за фільтр у шаблоні: вираз v-for="todo in todos.filter(...)" створює новий масив на кожному рендері компонента - навіть якщо змінилося щось зовсім не пов'язане зі списком.

Докладніше в документації: v-for разом з v-if

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання