Vuejs——(4)v-if、v-for


 

目錄(?)[+]

 

(二十)v-if

①標准v-if用法

簡單來說,該值為true則顯示該標簽,為false則不顯示;

如例:

 

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <div v-if="abc">{{abc.a}}</div>  
  3. </div>  
  4. <script>  
  5.     var vm = new Vue({  
  6.         el: '#app',  
  7.         data: {  
  8.             abc: {  
  9.                 a: "1"  
  10.             }  
  11.         }  
  12.     })<pre name="code" class="javascript">  

</script>

 

 
         

 

當abc這個對象存在時,顯示這一行數據,其內容為abc.a的值;

假如abc這個對象不存在,那么則不顯示;

 

也可以用另外一個變量來控制其是否顯示(能否顯示決定於該值隱式轉換為boolean類型時是true還是false);

例如假如上面有abc這個對象,但這個對象是空對象(沒有屬性a),但空對象隱式轉換后為true,因此會有div,但這個div里沒有內容;

 

 

②template v-if 包裝以同時影響多個html標簽;

即假如多個標簽(且他們是連續的),被一個變量控制是否顯示,那么每個都這么寫顯然太繁瑣,因此用一個template標簽將這些標簽包裹起來,用v-if標簽控制該template標簽是否顯示,實際渲染時,template標簽不會顯示,只會顯示其內的標簽;

如示例:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <template v-if="abc">  
  3.         <div>{{abc[0]}}</div>  
  4.         <div>{{abc[1]}}</div>  
  5.         <div>{{abc[2]}}</div>  
  6.     </template>  
  7. </div>  
  8. <script>  
  9.     var vm = new Vue({  
  10.         el: '#app',  
  11.         data: {  
  12.             abc: [1, 2, 3]  
  13.         }  
  14.     })  
  15. </script>  

由於非空數組是值為true,空數組的值為false,因此方便控制;

另外,這里只是演示,事實上更好的寫法的v-for來控制內部三個標簽來同時顯示(當然,如果不需要顯示全部的則不應該這么寫);

顯示內容:

<divid="app">

    <div>1</div>

    <div>2</div>

    <div>3</div>

</div>

 

 

③v-show     用於控制該標簽的display樣式

他的特點是,dom存在於頁面內,已經渲染、事件綁定完畢,區別只是是否顯示。

例如:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div v-show="a">{{test}}</div>  

a的值為true,則正常顯示;

a的值為false,則自動添加display:none

 

v-show不支持template寫法(即不能同時控制多個同級連續div);

 

④v-else v-if和v-show的補充語句;

即v-if和v-show的判斷為true時,不顯示v-else標簽的內容;否則顯示v-else標簽的內容。

 

例如:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <div v-show="a">{{test}}</div>  
  3.     <div v-else>def</div>  
  4. </div>  
  5. <script>  
  6.     var vm = new Vue({  
  7.         el: '#app',  
  8.         data: {  
  9.             a: true,  
  10.             test: "abc"  
  11.         }  
  12.     })  
  13. </script>  

顯示abc;

若把data中的a改為false,則顯示def;

 

另外,標簽之間需要連續,如以下,v-else則不能正常生效:

 

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div v-show="a">{{test}}</div>  
  2. <div>another</div>  
  3. <div v-else>def</div>  

 

另外,不要在組件的情況下使用v-else,而是采用v-show=”!變量名”來變相起到v-else的效果

 

 

 

⑤v-if和v-show的比較

 

 

 

v-if

v-show

渲染時間

第一次為真時

剛開始就渲染

切換形式

動態生成,局部編譯/卸載

控制display屬性

生成消耗

較小(只生成為真的部分)

較大(生成全部)

切換消耗

較大(切換時需要局部編譯)

較小(因為生成時已經渲染完成)


v-if是在第一次條件為真時,進行渲染(比如他下面還有其他組件);

v-show因為只是控制display的屬性,因此開始就會渲染;

 

 

(二十一)v-for列表渲染

①標准寫法

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <li v-for="i in items">{{i}}</li>  

【1】items是一個對象或者數組;

【2】該格式相當於for(var i in items){//略}

【3】插值的i相當於items[i]

【4】該li會被復制多個,然后依次被items[i]渲染,直到渲染完畢;

示例:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <ul>  
  3.         <li v-for="i in items">{{i}}</li>  
  4.     </ul>  
  5. </div>  
  6. <script>  
  7.     var vm = new Vue({  
  8.         el: '#app',  
  9.         data: {  
  10.             items: {  
  11.                 a: "1",  
  12.                 b: "2",  
  13.                 c: "3"  
  14.             }  
  15.         }  
  16.     })  
  17. </script>  

結果:

<divid="app">

    <ul>

        <li>1</li>

        <li>2</li>

        <li>3</li>

    </ul>

</div>

 

 

②索引編號:

在標簽里使用$index,即表示當前索引在v-for中的編號(從0開始);

例如上面改為:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <li v-for="i in items">{{i}}'s index is {{$index}}</li>  
顯示的是從0~2

 

③template v-for 用於包裹多個標簽的v-for

 

簡單來說,需要將多個標簽都用v-for遍歷,那么就需要用template標簽。

同樣,template在實際渲染的時候不會出現,只是起到一個包裹作用。

如代碼:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <ul>  
  3.         <template v-for="i in items">  
  4.             <li>Index is {{$index}}</li>  
  5.             <li>Content is {{i}}</li>  
  6.         </template>  
  7.     </ul>  
  8. </div>  
  9. <script>  
  10.     var vm = new Vue({  
  11.         el: '#app',  
  12.         data: {  
  13.             items: {  
  14.                 a: "1",  
  15.                 b: "2",  
  16.                 c: "3"  
  17.             }  
  18.         }  
  19.     })  
  20. </script>  

顯示結果是:

<ul>

        <li>Index is0</li><li>Content is 1</li>

        <li>Index is1</li><li>Content is 2</li>

        <li>Index is2</li><li>Content is 3</li>

</ul>

 

 

④監視數組變動(修改數組)

 

當data的某個屬性是一個數組時,用v-for可以遍歷,但顯然數組是可能變動的,因此對以下變動也進行數據綁定;

push()         數組末尾添加

pop()           數組末尾取出

shift()          數組開頭取出

unshift()      數組開頭添加

splice()        刪除並插入

sort()           排序

reverse()     數組順序顛倒

當利用以上方法變更數組時,被渲染的內容會實時更新;

 

 

⑤監視數組的改變(用另一個數組進行替換)

但數組從一個數組變為另一個數組時(記得,數組是按引用傳遞的),數據綁定依然生效;

但前提是使用以下方法:

filter()         過濾,參數是一個函數,取其返回值為true的元素被添加到新數組

concat()       合並兩個數組,返回的數組是合並后的

slice()          返回數組的拷貝,從開始索引到結束索引(前含后不含)

 

 

⑥track-by(以下推測不完全確定,因為我沒數據去測試)

按照說明,假如用一個新的對象數組來替換已有的對象數組(並且兩個對象數組其對象的屬性不同),那么由於v-for默認是通過數據對象的特征來決定已有作用域和DOM元素的復用程度,可能導致重新渲染整個列表(比如列表很大的話可能會導致效率很低)。

按照我的理解,大概就是從這樣一個數組:(我推測是這樣的)

 

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. items: [  
  2.     {name: "a", age: 10},  
  3.     {name: "b", age: 11},  
  4.     {name: "c", age: 12}  
  5. ]  

 

變成這樣

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. items = [  
  2.     {name: "A", height: 150},  
  3.     {name: "B", height: 160},  
  4.     {name: "C", height: 170}  
  5. ]  

會導致列表重新渲染,如果列表內容特別多,那么就可能帶來影響效率和性能。

 

解決這種方法的辦法,就是使用track-by,即加入一個包含某特定屬性的標識符,當這個屬性的標識符其值相等時,則盡可能復用這個已有對象的作用域和DOM元素。

例如標簽寫法如下:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <li v-for="item in items" track-by="id">{{item.name}}</li>  

數據從:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. items: [  
  2.     {id: 1, name: "a", age: 10},  
  3.     {id: 2, name: "b", age: 11},  
  4.     {id: 3, name: "c", age: 12}  
  5. ]  

變為:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. items = [  
  2.     {id: 3, name: "A", height: 150},  
  3.     {id: 2, name: "B", height: 160},  
  4.     {id: 1, name: "C", height: 170}  
  5. ]  

那么在替換時,會復用。

注意,復用並不是使用之前同id的對象所在的dom位置,例如並不會將name=C的元素放在原有的name=a的元素的位置(即使他們id都為1),而是依然根據數組下標的順序來顯示數據。

 

 

⑦track-by=”$index”(不確定+1)

當數組沒有某一個共同屬性時(比如上面的id),但依然需要復用的話,那么就用這個。

他會強制v-for進入原位更新模式,片斷不會被移動(我推測這個片斷指v-for的dom標簽),簡單的根據對應的索引的值來刷新dom,這種模式可以處理數組中重復的值。(應該是指對於重復的值,比如像上面那種id為同一個數值的,也可以正常復用)。

 

由於替換方式簡單暴力(索引肯定是一樣的),所以高效。

 

————————————————————————

 

這讓數據替換非常高效,但是也會付出一定的代價。因為這時DOM 節點不再映射數組元素順序的改變,不能同步臨時狀態(比如 <input> 元素的值)以及組件的私有狀態。因此,如果 v-for 塊包含 <input> 元素或子組件,要小心使用 track-by="$index"

 

——————我表示以上這段話沒看懂——————

如以下代碼,reverse()依然在起作用啊

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <ul>  
  3.         <li v-for="item in items" track-by="$index">{{item.name}}</li>  
  4.     </ul>  
  5.     <button onclick="chagne()">change</button>  
  6. </div>  
  7. <script>  
  8.     var vm = new Vue({  
  9.         el: '#app',  
  10.         data: {  
  11.             items: [  
  12.                 {id: 1, name: "a", age: 10},  
  13.                 {id: 2, name: "b", age: 11},  
  14.                 {id: 3, name: "c", age: 12}  
  15.             ]  
  16.         }  
  17.     })  
  18.     function chagne() {  
  19.         vm.items = [  
  20.             {id: 3, name: "A", height: 150},  
  21.             {id: 2, name: "B", height: 160},  
  22.             {id: 1, name: "C", height: 170}  
  23.         ];  
  24.         vm.items.reverse();  
  25.     }  
  26. </script>  

 

⑧數組的一些方法:

$set(索引, 被替換的值)

簡單來說,以下代碼是不會觸發數據綁定的:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. vm.items[0] = {name: "test"};  

替代方法是:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. vm.items.$set(0, {name: "test"});  

 

$remove(被移除的對象)

假如要移除某個對象(注意,由於對象是按引用傳遞,因此不能簡單用看起來一樣的對象來移除某個對象),可以直接使用這個方法。具體代碼是:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <script>  
  2.     var test = {name: "test"};  
  3.     var vm = new Vue({  
  4.         el: '#app',  
  5.         data: {  
  6.             items: [  
  7.                 {name: "a"},  
  8.                 {name: "b"},  
  9.                 {name: "c"}  
  10.             ]  
  11.         }  
  12.     })  
  13.     vm.items.push(test);  
  14.     function chagne() {  
  15.         vm.items.$remove(test);  
  16.         //vm.items.$remove({name: "test"}); //注意,這種寫法是錯誤的  
  17.     }  
  18. </script>  

他相當於先用indexOf找到該對象的索引,再用splice來從數組中移除該對象。

 

 

Object.freeze(數組的對象元素)

假如數組中某一個元素(他是個對象)被Object.freeze凍結了,需要明確指定track-by,這種情況下,如果Vuejs不能自動追蹤對象,將給出一條警告。

 

——不懂!——

反正被這樣搞的對象,其值不能被修改,修改其值也沒用(修改無效)

 

 

⑨$key用於獲取被遍歷對象的key值

即js代碼中,for(var i in items)中的i,記得,在v-for里,其是items[i]

但僅對object對象生效,對數組無效(數組可以使用$index)

如代碼:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <ul>  
  3.         <li v-for="item in items" track-by="$index">{{$key}}: {{item}}</li>  
  4.     </ul>  
  5. </div>  
  6. <script>  
  7.     var test = {name: "test"};  
  8.     var vm = new Vue({  
  9.         el: '#app',  
  10.         data: {  
  11.             items: {  
  12.                 name: "wd",  
  13.                 age: "27",  
  14.                 sex: "man"  
  15.             }  
  16.         }  
  17.     })  
  18. </script>  

 

顯示內容為:

  • name: wd
  • age: 27
  • sex: man

 

這個key也可以使用別名,方法很簡單,標簽如下寫:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <li v-for="(a_key,item) in items" track-by="$index">{{a_key}}: {{item}}</li>  

這里的a_key就相當於$key

且他們之間不會互相沖突,並能同時使用。

 

注意:別名對數組有效,$key對數組無效

 

 

⑩遍歷順序:

按照Object.keys()的結果遍歷

例如:

[javascript]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. var a = {a: 1, b: 2, c: 3};  
  2. Object.keys(a)  

其返回結果是:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. ["a", "b", "c"]  

然后會按照這個順序來遍歷,但其結果可能會因為JavaScript引擎的不同而不同(受影響的是對象);

 

 

⑪v-for一個數字

可以對一個數字使用v-for,例如:


[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <li v-for="(a_key,item) in 10" track-by="$index">{{a_key}}: {{item}}</li>  

【1】這個數字可以是一個浮點數;

【2】從0開始,到小於這個數字的最大整數(例如10那么則到9,10.1則到10);

 

 

⑫顯示過濾、排序后的結果:

【1】使用計算屬性(computed),返回過濾、排序后的結果;

優點:可自定義,功能更強大,更靈活;

缺點:麻煩;

 

【2】使用內置過濾器filterBy和orderBy

鏈接:http://cn.vuejs.org/api/#filterBy

 

 

【3】filterBy

簡單來說,如果沒有被過濾的內容,則被過濾掉,

如果是對象,則對key和val都有效(都會被檢索),

如代碼:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <input v-model="input"/>  
  3.     <p>請在輸入框內輸入內容,只會將符合條件的內容顯示出來</p>  
  4.     <ul>  
  5.         <li v-for="item in items|filterBy input">{{item}}</li>  
  6.     </ul>  
  7. </div>  
  8. <script>  
  9.     var test = {name: "test"};  
  10.     var vm = new Vue({  
  11.         el: '#app',  
  12.         data: {  
  13.             input: "",  
  14.             items: {  
  15.                 name: "wd",  
  16.                 age: "27",  
  17.                 sex: "man"  
  18.             }  
  19.         }  
  20.     })  
  21. </script>  


注意:

(1)假如輸入‘a’,雖然name屬性和age屬性的值沒有a,但是其key有,所以依然會顯示;

(2)不能只對其值(如果v-for的是一個對象的話)過濾生效,比如

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <li v-for="item in items|filterBy input in 'item'">{{item}}</li>  

是無效的寫法!

(3)如果要使用(2)中的方法,必須只能面對對象數組;

如以下:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <input v-model="input"/>  
  3.     <p>請在輸入框內輸入內容,只會顯示name符合的</p>  
  4.     <ul>  
  5.         <li v-for="(key,item) in items|filterBy input in 'name'">age:{{item.age}},name:{{item.name}}</li>  
  6.     </ul>  
  7. </div>  
  8. <script>  
  9.     var test = {name: "test"};  
  10.     var vm = new Vue({  
  11.         el: '#app',  
  12.         data: {  
  13.             input: "",  
  14.             items: [  
  15.                 {age: 1, name: "abc"},  
  16.                 {age: 2, name: "ab"},  
  17.                 {age: 3, name: "c"}  
  18.             ]  
  19.         }  
  20.     })  
  21. </script>  

(4)多字段過濾

如以下:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <li v-for="(key,item) in items|filterBy input in 'name''age'">age:{{item.age}},name:{{item.name}}</li>  

無論是age符合或者是name符合,都可以正常顯示。

 

(5)動態多字段過濾

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <input v-model="input"/>  
  3.     <p>請在輸入框內輸入內容,只會顯示name符合的</p>  
  4.     <ul>  
  5.         <li v-for="(key,item) in items|filterBy input in List">age:{{item.age}},name:{{item.name}}</li>  
  6.     </ul>  
  7.     <button @click="change">點擊搜索age</button>  
  8. </div>  
  9. <script>  
  10.     var test = {name: "test"};  
  11.     var vm = new Vue({  
  12.         el: '#app',  
  13.         data: {  
  14.             input: "",  
  15.             List: "name",  
  16.             items: [  
  17.                 {age: 1, name: "abc"},  
  18.                 {age: 2, name: "ab"},  
  19.                 {age: 3, name: "c"}  
  20.             ]  
  21.         },  
  22.         methods: {  
  23.             change: function () {  
  24.                 this.List = "age";  
  25.             }  
  26.         }  
  27.     })  
  28. </script>  

(1)初始過濾name,點擊按鈕過濾age;

(2)List可以是字符串,也可以是數組;

(3)動態改變依然會生效;

 

 

【4】orderBy

用於排序的過濾,可以加參數,參數>=0則為正序排序,<0則為倒序排序

普通寫法:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <li v-for="(key,item) in items|orderBy 'age'">age:{{item.age}},name:{{item.name}}</li>  

根據age值,正序排列,顯示:

  • age:2,name:ab
  • age:3,name:c
  • age:4,name:abc

 

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <li v-for="(key,item) in items|orderBy 'name' -1"> age:{{item.age}},name:{{item.name}}</li>  

根據name,倒序排列(因為參數為-1,其<0),字符串的排列順序為逐字母比較順序。

 

也可以使用函數作為排序條件,具體而言,如代碼:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. <div id="app">  
  2.     <input v-model="input"/>  
  3.     <p>請在輸入框內輸入內容,只會顯示name符合的</p>  
  4.     <ul>  
  5.         <li v-for="(key,item) in items|orderBy test">age:{{item.age}},name:{{item.name}}</li>  
  6.     </ul>  
  7.     <button @click="test">點擊搜索age</button>  
  8. </div>  
  9. <script>  
  10.     var test = {name: "test"};  
  11.     var vm = new Vue({  
  12.         el: '#app',  
  13.         data: {  
  14.             items: [  
  15.                 {age: 5, name: "abc"},  
  16.                 {age: 2, name: "ab"},  
  17.                 {age: 13, name: "c"},  
  18.                 {age: 33, name: "c"},  
  19.                 {age: 3, name: "c"}  
  20.             ]  
  21.         },  
  22.         methods: {  
  23.             test: function (a, b) {  
  24.                 return a.age - b.age;  
  25.             }  
  26.         }  
  27.     })  
  28. </script>  

他會根據age的值差進行排序,簡單來說,a-b則為從小到大(這里指的是被排序的屬性)),b-a則為從大到小。

 

如圖結果為:

  • age:2,name:ab
  • age:3,name:c
  • age:5,name:abc
  • age:13,name:c
  • age:33,name:c


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM