在vue.js里面,v-for和v-if是可以一起使用作用在某個元素上,網上看到一篇文章說永遠不要把v-for和v-if同時用在同一個元素上,感覺有點瞎扯,官網也注明了可以一起使用的,還把兩個指令的優先級給說明了:
當v-if和v-for一起使用時,v-for的優先級更高,為了方便理解舉個栗子:
<div id="app"> <ul> <li v-for="item in Nums" v-if="item%2==0">{{item}}->偶數</li> <li v-else-if="item%3==0">{{item}}->可以被3整除的奇數</li> <li v-else>{{item}}->其它奇數</li> </ul> </div> <script> new Vue({ el:"#app", data:{ Nums:[0,1,2,3,4,5,6,7,8,9,10,11,12] } }) </script>
比較簡單昂,就是用v-for循環一個數組,然后分別用v-if、v-else-if和v-else做判斷,渲染如下:
很多人剛開始一起用v-for和v-if時多少有點不習慣,如下:
<li v-for="item in Nums" v-if="item%2==0">{{item}}->偶數</li> <li v-else-if="item%3==0">{{item}}->可以被3整除的奇數</li> <li v-else>{{item}}->其它奇數</li>
第2和第3行<li>標簽的代碼里用到了item,但是item是在第一個<li>里定義了,這樣不是不能獲取到的嗎?其實在源碼內部,這三行代碼都封裝為一個返回一個三元表達式的函數了,作為v-for實現代碼的一個參數,然后在v-for遍歷數組時依次執行這函數來輸出數據的
對於例子里的模板經過在編譯階段生成AST對象后會調用generate函數生成render函數,如下:
它會優先處理v-for指令,然后處於v-if、v-else-if、v-else之類的指令(可以看到v-once的優先級高於v-for和v-else),對於例子里的模板生成的render函數如下:
_c( 'div', {attrs: {"id": "app"}}, [ _c( 'ul', _l((Nums),function(item) { return (item % 2 == 0) ? _c('li', [_v(_s(item) + "->偶數")]) : (item % 3 == 0) ? _c('li', [_v(_s(item) + "->可以被3整除的奇數")]) : _c('li', [_v(_s(item) + "->其它奇數")]) }) ) ] )
writer by:大沙漠 QQ:22969969
_l對應的就是v-for的實現函數,可以看到vue內部把v-if的代碼封裝為了一個匿名函數,傳遞給了v-for,而在v-for最后實現時,它是通過遍歷Nums,依次執行參數2的,_l對應的函數如下:
function renderList(val, render) { //渲染v-for指令 var ret, i, l, keys, key; if (Array.isArray(val) || typeof val === 'string') { //如果val是個數組 ret = new Array(val.length); //將ret定義成val一樣大小的數組 for (i = 0, l = val.length; i < l; i++) { //遍歷val數組 ret[i] = render(val[i], i); //依次調用render函數,參數1為值 參數2為索引 返回VNode,並把結果VNode保存到ret里面 ;例子里的Nums是個數組,因此是執行到這里的 } } else if (typeof val === 'number') { ret = new Array(val); for (i = 0; i < val; i++) { ret[i] = render(i + 1, i); } } else if (isObject(val)) { //如果val是一個對象 keys = Object.keys(val); ret = new Array(keys.length); for (i = 0, l = keys.length; i < l; i++) { key = keys[i]; ret[i] = render(val[key], key, i); //執行的時候傳遞三個參數,分別是值、key和索引 } } if (isDef(ret)) { //如果ret存在(成功調用了) (ret)._isVList = true; //則給該數組添加一個_isVList屬性,值為true } return ret //最后返回ret }
對於對象來說,邏輯是一樣的,只是在邏輯上多個幾個細分支,就不介紹了。