- v-if 與 v-for簡介
- v-if
- v-for
- v-if & v-for使用
- v-if 與 v-for優先級比較
- vue2 中,v-for的優先級高于v-if
- 例子進行分析
- vue3 v-if 具有比 v-for 更高的優先級
- 例子進行分析
- vue2 中,v-for的優先級高于v-if
- 總結
- 在vue2中,v-for的優先級高于v-if
- 在vue3中,v-if的優先級高于v-for
咋一聽到這個題,如果自己沒有試驗過感覺還真容易說錯,就像是會進入一個“思維誤區”
就會理所當然的想如果這兩個指令同時出現一個標簽那是不是應該先if判斷是否存在才會去渲染for的循環結構?
但實際是這樣嗎?
v-if 與 v-for簡介
v-if
v-if 指令用于條件性地渲染一塊內容。這塊內容只會在指令的表達式返回 true值的時候被渲染。
v-if是Vue.js中的一個指令,用于條件渲染,根據綁定的表達式的值的真假情況來決定是否顯示或隱藏元素。
當v-if的表達式值為true時,元素會被渲染出來;當v-if的表達式值為false時,元素不會被渲染出來。
例如,下面代碼中,如果isShow為true,則div元素將會被渲染,否則不會被渲染:
<template><div v-if="isShow">show content</div>
</template>
需要注意的是,v-if指令會根據表達式的值動態地添加或刪除元素,因此如果有頻繁的切換操作,會影響性能。
此時可以考慮使用v-show指令,它只是簡單地控制元素的顯示或隱藏,并沒有頻繁的添加或刪除元素。
v-for
v-for 指令基于一個數組來渲染一個列表。v-for 指令需要使用 item in items 形式的特殊語法,其中 items 是源數據數組或者對象,而 item 則是被迭代的數組元素的別名。
v-for使用 的時候,建議設置key值,并且保證每個key值是獨一無二的,這便于diff算法進行優化。
v-for是Vue.js中的一個指令,用于循環渲染數組或對象的數據。
v-for的用法有兩種情況:
- 遍歷數組:
可以通過v-for指令循環渲染一個數組,將數組中的每個元素渲染成對應的元素或組件。語法形式為:v-for="item in array"
。
例如,下面代碼中使用v-for指令循環渲染一個數組list中的每個元素:
<template><div><ul><li v-for="item in list" :key="item.id">{{ item.name }}</li></ul></div>
</template><script>
export default {data() {return {list: [{ id: 1, name: 'Apple' },{ id: 2, name: 'Banana' },{ id: 3, name: 'Orange' }]};}
}
</script>
- 遍歷對象:
可以通過v-for指令循環渲染一個對象的屬性,將對象的屬性和值渲染成對應的元素或組件。語法形式為:v-for="value, key in object"
。
例如,下面代碼中使用v-for指令循環渲染一個對象info的每個屬性:
<template><div><ul><li v-for="(value, key) in info" :key="key">{{ key }}: {{ value }}</li></ul></div>
</template><script>
export default {data() {return {info: {name: 'John',age: 25,gender: 'Male'}};}
}
</script>
需要注意的是,在使用v-for時,需要為每個循環的元素或組件添加唯一的key屬性,以便Vue.js能夠跟蹤每個節點的身份,并且在更新時進行高效的DOM操作。
更多詳細內容,請微信搜索“前端愛好者
“, 戳我 查看 。
v-if & v-for使用
<ul> <li v-for='user in users' :key='user.id'>{{user.name}}</li>
</ul>
<footer v-if='user'>{{user}}</footer>
v-if 與 v-for優先級比較
- 在vue2中,v-for的優先級高于v-if
- 在vue3中,v-if的優先級高于v-for(Vue 3.0 已經調整了v-if和v-for 的優先級,故不存在渲染性能問題。)
vue2 中,v-for的優先級高于v-if
當 v-if 與 v-for 一起使用時,v-for 具有比 v-if 更高的優先級。
官方文檔:https://v2.cn.vuejs.org/v2/guide/conditional.html#v-if-%E4%B8%8E-v-for-%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8
在 Vue 2 中,不推薦在同一個元素上同時使用 v-if 和 v-for,主要是由于可能引發的性能問題和邏輯混淆。當 v-if 和 v-for 結合使用時,會導致以下問題:
-
性能問題: 當 v-if 和 v-for 同時存在于同一個元素上時,Vue 會在每次循環迭代時都重新渲染和銷毀元素。這可能會導致不必要的 DOM 更新和性能下降,特別是在較長的列表上。這是因為每次循環迭代都會重新計算條件,并進行 DOM 操作。
-
邏輯混淆: 同時使用 v-if 和 v-for 會增加代碼的復雜性和理解難度。將條件和循環邏輯分離可以使代碼更加清晰,并讓開發人員更容易理解和維護。
例子進行分析
<template><div class="test-container"><div v-for="(item,index) in list" v-if="item === 9" :key="item" ></div></div>
</template>
<script>export default {data(){return {numberArr:[1,2,3,4,5,6,7,8,9,10]}}};
</script>
<style scoped>
</style>
但是本段代碼實際的邏輯為
this.numberArr.map(function (item,index) {if (item===9) {return item}
})
相反,最佳實踐是:
將條件渲染 (v-if) 和列表渲染 (v-for) 分開處理。
可以使用計算屬性或方法來處理數據,然后在模板中分別使用 v-if 和 v-for。
以下是一個示例代碼:
<template><div><div v-if="showDiv" v-for="item in filteredItems" :key="item.id">{{ item.name }}</div></div>
</template><script>
export default {data() {return {showDiv: true,items: [{ id: 1, name: 'Item 1', isActive: true },{ id: 2, name: 'Item 2', isActive: false },{ id: 3, name: 'Item 3', isActive: true }]}},computed: {filteredItems() {return this.items.filter(item => item.isActive);}}
}
</script>
在上述示例中,我們使用了計算屬性 filteredItems 來過濾具有 isActive 屬性的項目。
然后,我們在模板中使用 v-for 來渲染過濾后的結果,并使用 v-if 來條件性地渲染每個元素。這樣可以保持邏輯的清晰和性能的優化。
vue3 v-if 具有比 v-for 更高的優先級
當 v-if 與 v-for 一起使用時,v-if 具有比 v-for 更高的優先級。
官方文檔:https://cn.vuejs.org/guide/essentials/list.html#v-for-with-v-if
<!--這會拋出一個錯誤,因為屬性 todo 此時沒有在該實例上定義
-->
<li v-for="todo in todos" v-if="!todo.isComplete">{{ todo.name }}
</li>
推薦: 在外新包裝一層 再在其上使用 v-for 可以解決這個問題 (這也更加明顯易讀):
<template v-for="todo in todos"><li v-if="!todo.isComplete">{{ todo.name }}</li>
</template>
例子進行分析
<template><div class="test-container"><div v-for="(item,index) in numberArr" v-if="item === 9" :key="item"></div></div>
</template>
<script>
export default {data(){return {numberArr: [1,2,3,4,5,6,7,8,9,10] //需要遍歷的數據}}
};
</script>
<style scoped>
</style>
由于 v-if 優先級高,導致頁面并沒有進行渲染,控制臺報錯。
以下為控制臺報錯信息
[Vue warn]: Property "index" was accessed during render but is not defined on instance.
但是下面這種用法控制臺并不會報錯但是會警告
<template><div class="test-container"><ul><li v-for="(item, index) in objList" :key="index" v-if="item.isShow">{{ item.name }}</li></ul></div>
</template>
<script>export default {data(){return {objList:[{ name: 'obj2', isShow: false },{ name: 'obj2', isShow: true },]}}};
</script>
<style scoped>
</style>
但是這種寫法也會有一個問題,無論是否符合v-if的條件都進行了報錯
官方推薦的寫法是這樣的, 把 v-for 移動到容器元素上,例如ul,ol 或者外面包裹一層 template
<template><div class="test-container"><ul><template v-for="(item, index) in objList" :key="index"><li v-if="item.isShow">{{ item.name }}</li></template></ul></div>
</template>
<script>export default {data(){return {objList:[{ name: 'obj2', isShow: false },{ name: 'obj2', isShow: true },]}}};
</script>
<style scoped>
</style>
但如果想要有條件地跳過循環的執行,那么可以將v-if置于外層元素或者template上。
例如這樣:
<template><div class="test-container"><ul v-if="objList.length"><li v-for="(item, index) in objList" :key="index">{{ item.name }}</li></ul></div>
</template>
<script>
export default {data(){return {objList:[{ name: 'obj2', isShow: false },{ name: 'obj2', isShow: true },]}}
};
</script>
<style scoped>
</style>
總結
在vue2中,v-for的優先級高于v-if
Vue 會在每次循環迭代時都重新渲染和銷毀元素。
v-for比v-if優先級更高(可以說清結論的來源更好)。
如果同時出現在同一個標簽上,則每次渲染都會先執行循環再進行條件判斷,會造成較大的性能浪費。
解決辦法有兩種:
- 先在外層套一個template來放置v-if,再嵌套v-for。
- 借助computed計算屬性代替v-if。
在vue3中,v-if的優先級高于v-for
注:Vue 3.0 已經調整了v-if和v-for 的優先級,故不存在渲染性能問題。
參考文檔
- https://www.nowcoder.com/discuss/513503986318696448
- https://baijiahao.baidu.com/s?id=1766197354040903874&wfr=spider&for=pc