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
函數
<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
就能得到渲染函數
_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>
ƒ 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 genOnce(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.tag === '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 }) } }