1. 程式人生 > 其它 >為什麼Vue中的v-if和v-for不建議一起用?

為什麼Vue中的v-if和v-for不建議一起用?

技術標籤: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 高

三、注意事項

  1. 永遠不要把 v-if 和 v-for 同時用在一個元素上,帶來效能方面的浪費(每次渲染都會先迴圈再進行條件判斷)
  2. 如果避免出現這種情況,則在外層巢狀 template (頁面渲染不生成dom節點),再這一層進行 v-if 判斷,然後再內部進行 v-for 迴圈
<template v-if="isShow">
	<p v-for="item in items">
</template>
  1. 如果條件出現再迴圈內部,可通過計算屬性 computed 提前過濾掉那些不需要顯示的項
computed:{
	items:function(){
		return this.list.filter(function(item){
			return item.isShow
		})
	}
}

參考文獻