Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 debugging reference for reactivity issues, computed errors, watcher bugs, async failures, and SSR hydration problems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/no-v-if-with-v-for.md
1---2title: Never Use v-if and v-for on the Same Element3impact: HIGH4impactDescription: Causes confusing precedence issues and Vue 2 to 3 migration bugs5type: capability6tags: [vue3, v-if, v-for, conditional-rendering, list-rendering, eslint]7---89# Never Use v-if and v-for on the Same Element1011**Impact: HIGH** - Using `v-if` and `v-for` on the same element creates ambiguous precedence that differs between Vue 2 and Vue 3. In Vue 2, `v-for` had higher precedence; in Vue 3, `v-if` has higher precedence. This breaking change causes subtle bugs during migration and makes code intent unclear.1213The ESLint rule `vue/no-use-v-if-with-v-for` enforces this best practice.1415## Task Checklist1617- [ ] Never place v-if and v-for on the same element18- [ ] For filtering list items: use a computed property that filters the array19- [ ] For hiding entire list: wrap with `<template v-if>` around the v-for20- [ ] Enable eslint-plugin-vue rule `vue/no-use-v-if-with-v-for`2122**Incorrect:**23```html24<!-- WRONG: v-if and v-for on same element - ambiguous precedence -->25<template>26<!-- Intent: show only active users -->27<li v-for="user in users" v-if="user.isActive" :key="user.id">28{{ user.name }}29</li>30</template>31```3233```html34<!-- WRONG: Hiding entire list conditionally -->35<template>36<li v-for="user in users" v-if="shouldShowList" :key="user.id">37{{ user.name }}38</li>39</template>40```4142```html43<!-- WRONG: Vue 3 precedence issue -->44<template>45<!-- In Vue 3, v-if runs FIRST, so 'user' is undefined! -->46<li v-for="user in users" v-if="user.isActive" :key="user.id">47{{ user.name }}48</li>49<!-- Error: Cannot read property 'isActive' of undefined -->50</template>51```5253**Correct:**54```html55<!-- CORRECT: Filter with computed property -->56<template>57<li v-for="user in activeUsers" :key="user.id">58{{ user.name }}59</li>60</template>6162<script setup>63import { computed } from 'vue'6465const props = defineProps(['users'])6667const activeUsers = computed(() =>68props.users.filter(user => user.isActive)69)70</script>71```7273```html74<!-- CORRECT: Wrap with <template v-if> for conditional list -->75<template>76<template v-if="shouldShowList">77<li v-for="user in users" :key="user.id">78{{ user.name }}79</li>80</template>81</template>82```8384```html85<!-- CORRECT: v-if inside the loop (per-item condition) -->86<template>87<ul>88<template v-for="user in users" :key="user.id">89<li v-if="user.isActive">90{{ user.name }}91</li>92</template>93</ul>94</template>95```9697## Vue 2 vs Vue 3 Precedence Change9899```javascript100// Vue 2: v-for evaluated first101// <li v-for="user in users" v-if="user.isActive">102// Equivalent to: users.forEach(user => { if (user.isActive) render(user) })103104// Vue 3: v-if evaluated first105// <li v-for="user in users" v-if="user.isActive">106// Equivalent to: if (user.isActive) users.forEach(user => render(user))107// Problem: 'user' doesn't exist yet when v-if runs!108```109110## Why Computed Properties Are Better111112```javascript113// Benefits of filtering via computed:114// 1. Clear separation of concerns (logic vs template)115// 2. Cached - only recalculates when dependencies change116// 3. Reusable - can be used elsewhere in component117// 4. Testable - can unit test the filtering logic118// 5. No ambiguity about intent119120const activeUsers = computed(() =>121users.value.filter(u => u.isActive)122)123124// Can add more complex filtering125const filteredUsers = computed(() =>126users.value127.filter(u => u.isActive)128.filter(u => u.role === selectedRole.value)129.sort((a, b) => a.name.localeCompare(b.name))130)131```132133## Reference134- [Vue.js Style Guide - Avoid v-if with v-for](https://vuejs.org/style-guide/rules-essential.html#avoid-v-if-with-v-for)135- [Vue 3 Migration Guide - v-if vs v-for Precedence](https://v3-migration.vuejs.org/breaking-changes/v-if-v-for)136- [ESLint Plugin Vue - no-use-v-if-with-v-for](https://eslint.vuejs.org/rules/no-use-v-if-with-v-for)137