Использование v-for
и v-if
на одном элементе считается антипаттерном во Vue.js. Разберем причины этого и правильные альтернативы.
Во Vue 2.x v-for
имеет более высокий приоритет, чем v-if
. Это означает:
<!-- Плохая практика -->
<div v-for="item in items" v-if="item.isActive">
{{ item.name }}
</div>
Фактически выполняется как:
v-if
items
вызывают полный перерендерЛучший подход - предварительная фильтрация данных:
computed: {
activeItems() {
return this.items.filter(item => item.isActive)
}
}
<div v-for="item in activeItems" :key="item.id">
{{ item.name }}
</div>
Если computed не подходит:
<template v-for="item in items">
<div v-if="item.isActive" :key="item.id">
{{ item.name }}
</div>
</template>
Для простых случаев (менее предпочтительно):
<div v-for="item in items.filter(i => i.isActive)" :key="item.id">
{{ item.name }}
</div>
В Vue 3 приоритеты изменились:
v-if
имеет более высокий приоритет, чем v-for
Неправильно:
<ul>
<li v-for="user in users" v-if="user.isActive" :key="user.id">
{{ user.name }}
</li>
</ul>
Правильно:
computed: {
activeUsers() {
return this.users.filter(user => user.isActive)
}
}
<ul>
<li v-for="user in activeUsers" :key="user.id">
{{ user.name }}
</li>
</ul>
Единственное исключение - когда нужно:
Пример допустимого использования:
<ul v-if="shouldShowList">
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
Разница в производительности:
Совместное использование v-for
и v-if
на одном элементе снижает производительность, усложняет поддержку кода и может привести к неожиданным результатам. Всегда предпочитайте предварительную фильтрацию данных через computed-свойства или разделяйте директивы с помощью <template>
.