為什麼Vue中的v-if和v-for不建議一起用?
阿新 • • 發佈:2020-12-19
技術標籤:v-if和v-for的理解
一、作用
v-if 指令用於條件性地渲染一塊內容。這塊內容只會在指令的表示式返回 true 值的時候被渲染
v-for 指令基於一個數組來渲染一個列表。 v-for 指令需要使用 item in items 形式的特殊語法,其中 items 是源資料陣列或者物件,而 item 則是被迭代的陣列元素的別名
在 v-for 的時候,建議設定 key 值,並且保證每個 key 值是獨一無二的,這便與 diff 演算法進行優化
兩者在用法上
<Modal v-if="isShow" />
<li v-for=" item in items" :key="item.id">{{ item.label }}</li>
二、優先順序
v-if 與 v-for 都是 vue 模板系統中的指令
在 vue 模板編譯的時候,會將指令系統轉化成可執行的 render 函式
示例
編寫一個 p 標籤,同時使用 v-if 和 v-for
<div id="app">
<p v-if="isShow" v-for="item in items">{{ item.title }}</p>
</div>
建立 vue 例項,存放 isShow 與 items 資料
const app = new Vue({
el:"#app",
data(){
return{
items:[
{ title:"foo" },
{ title:"baz" }
]
}
},
computed:{
isShow(){
return this.items && this.items.length > 0
}
}
})
模板指令的程式碼都會生成在 render 函式中,通過 app.$options.render 就能得到渲染函式
f anonymous(){
with(this){
_c('div',{ attrs:{ "id":"app" }},
_l((items),function(item)
{ return (isShow)?_c('p',[_v("\n"+_s(item.title)+"\n")]):_e()}),0)
}
}
_ l 是 vue 的列表渲染函式,函式內部都會進行一次 if 判斷
初步得到結論: v-for 優先順序是比 v-if 高
再將 v-for 與 v-if 置於不同標籤
<div id="app">
<template v-if="isShow">
<p v-for="item in items">{{ item.title }}</p>
</template>
</div>
再輸出下 render 函式
f anonymous(){
with(this){return
_c('div',{attrs:{"id":"app"}},
[(isShow)?[_v("\n"),
_l((items),function(item){return _c('p',[_v(_s(item.title))])})]:_e()],2)}
}
這時候我們可以看到,v-for 與 v-if 作用再不同標籤時候,是先進性判斷,再進行列表的渲染
我們再檢視下 vue 原始碼
原始碼位置:\vue-dev\src\compiler\codegen\index.js
export function genElement(el:ASTElement,state:CodegenState):string{
if(el.parent){
el.pre = el.pre || el.parent.pre
}
if(el.staticRoot && !el.staticProcessed){
return genStatic(el,state)
}else if(el.once && !el.onceProcessed){
return genOnec(el,state)
}else if(el.for && !el.forProcessed){
return genFor(el,state)
}else if(el.if && !el.ifProcessed){
return genIf(el,state)
}else if(el.tab === 'template' && !el.slotTarget && !state.pre){
return genChildren(el,state) || 'void 0'
}else if(el.tag === 'slot'){
return genSlot(el,state)
}else{
//component or element
...
}
}
在進行 if 判斷的時候,v-for 是比 v-if 先進行判斷
最終結論:v-for 優先順序比 v-if 高
三、注意事項
- 永遠不要把 v-if 和 v-for 同時用在一個元素上,帶來效能方面的浪費(每次渲染都會先迴圈再進行條件判斷)
- 如果避免出現這種情況,則在外層巢狀 template (頁面渲染不生成dom節點),再這一層進行 v-if 判斷,然後再內部進行 v-for 迴圈
<template v-if="isShow">
<p v-for="item in items">
</template>
- 如果條件出現再迴圈內部,可通過計算屬性 computed 提前過濾掉那些不需要顯示的項
computed:{
items:function(){
return this.list.filter(function(item){
return item.isShow
})
}
}