版權聲明:出處http://blog.csdn.net/qq20004604
(二十)v-if
①標准v-if用法
簡單來說,該值為true則顯示該標簽,為false則不顯示;
如例:
- <div id="app">
- <div v-if="abc">{{abc.a}}</div>
- </div>
- <script>
- var vm = new Vue({
- el: '#app',
- data: {
- abc: {
- a: "1"
- }
- }
- })<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標簽不會顯示,只會顯示其內的標簽;
如示例:
- <div id="app">
- <template v-if="abc">
- <div>{{abc[0]}}</div>
- <div>{{abc[1]}}</div>
- <div>{{abc[2]}}</div>
- </template>
- </div>
- <script>
- var vm = new Vue({
- el: '#app',
- data: {
- abc: [1, 2, 3]
- }
- })
- </script>
由於非空數組是值為true,空數組的值為false,因此方便控制;
另外,這里只是演示,事實上更好的寫法的v-for來控制內部三個標簽來同時顯示(當然,如果不需要顯示全部的則不應該這么寫);
顯示內容:
<divid="app">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
③v-show 用於控制該標簽的display樣式
他的特點是,dom存在於頁面內,已經渲染、事件綁定完畢,區別只是是否顯示。
例如:
- <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標簽的內容。
例如:
- <div id="app">
- <div v-show="a">{{test}}</div>
- <div v-else>def</div>
- </div>
- <script>
- var vm = new Vue({
- el: '#app',
- data: {
- a: true,
- test: "abc"
- }
- })
- </script>
顯示abc;
若把data中的a改為false,則顯示def;
另外,標簽之間需要連續,如以下,v-else則不能正常生效:
- <div v-show="a">{{test}}</div>
- <div>another</div>
- <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列表渲染
①標准寫法
- <li v-for="i in items">{{i}}</li>
【1】items是一個對象或者數組;
【2】該格式相當於for(var i in items){//略}
【3】插值的i相當於items[i]
【4】該li會被復制多個,然后依次被items[i]渲染,直到渲染完畢;
示例:
- <div id="app">
- <ul>
- <li v-for="i in items">{{i}}</li>
- </ul>
- </div>
- <script>
- var vm = new Vue({
- el: '#app',
- data: {
- items: {
- a: "1",
- b: "2",
- c: "3"
- }
- }
- })
- </script>
結果:
<divid="app">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
②索引編號:
在標簽里使用$index,即表示當前索引在v-for中的編號(從0開始);
例如上面改為:
- <li v-for="i in items">{{i}}'s index is {{$index}}</li>
③template v-for 用於包裹多個標簽的v-for
簡單來說,需要將多個標簽都用v-for遍歷,那么就需要用template標簽。
同樣,template在實際渲染的時候不會出現,只是起到一個包裹作用。
如代碼:
- <div id="app">
- <ul>
- <template v-for="i in items">
- <li>Index is {{$index}}</li>
- <li>Content is {{i}}</li>
- </template>
- </ul>
- </div>
- <script>
- var vm = new Vue({
- el: '#app',
- data: {
- items: {
- a: "1",
- b: "2",
- c: "3"
- }
- }
- })
- </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元素的復用程度,可能導致重新渲染整個列表(比如列表很大的話可能會導致效率很低)。
按照我的理解,大概就是從這樣一個數組:(我推測是這樣的)
- items: [
- {name: "a", age: 10},
- {name: "b", age: 11},
- {name: "c", age: 12}
- ]
變成這樣
- items = [
- {name: "A", height: 150},
- {name: "B", height: 160},
- {name: "C", height: 170}
- ]
會導致列表重新渲染,如果列表內容特別多,那么就可能帶來影響效率和性能。
解決這種方法的辦法,就是使用track-by,即加入一個包含某特定屬性的標識符,當這個屬性的標識符其值相等時,則盡可能復用這個已有對象的作用域和DOM元素。
例如標簽寫法如下:
- <li v-for="item in items" track-by="id">{{item.name}}</li>
數據從:
- items: [
- {id: 1, name: "a", age: 10},
- {id: 2, name: "b", age: 11},
- {id: 3, name: "c", age: 12}
- ]
變為:
- items = [
- {id: 3, name: "A", height: 150},
- {id: 2, name: "B", height: 160},
- {id: 1, name: "C", height: 170}
- ]
那么在替換時,會復用。
注意,復用並不是使用之前同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()依然在起作用啊
- <div id="app">
- <ul>
- <li v-for="item in items" track-by="$index">{{item.name}}</li>
- </ul>
- <button onclick="chagne()">change</button>
- </div>
- <script>
- var vm = new Vue({
- el: '#app',
- data: {
- items: [
- {id: 1, name: "a", age: 10},
- {id: 2, name: "b", age: 11},
- {id: 3, name: "c", age: 12}
- ]
- }
- })
- function chagne() {
- vm.items = [
- {id: 3, name: "A", height: 150},
- {id: 2, name: "B", height: 160},
- {id: 1, name: "C", height: 170}
- ];
- vm.items.reverse();
- }
- </script>
⑧數組的一些方法:
$set(索引, 被替換的值)
簡單來說,以下代碼是不會觸發數據綁定的:
- vm.items[0] = {name: "test"};
替代方法是:
- vm.items.$set(0, {name: "test"});
$remove(被移除的對象)
假如要移除某個對象(注意,由於對象是按引用傳遞,因此不能簡單用看起來一樣的對象來移除某個對象),可以直接使用這個方法。具體代碼是:
- <script>
- var test = {name: "test"};
- var vm = new Vue({
- el: '#app',
- data: {
- items: [
- {name: "a"},
- {name: "b"},
- {name: "c"}
- ]
- }
- })
- vm.items.push(test);
- function chagne() {
- vm.items.$remove(test);
- //vm.items.$remove({name: "test"}); //注意,這種寫法是錯誤的
- }
- </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)
如代碼:
- <div id="app">
- <ul>
- <li v-for="item in items" track-by="$index">{{$key}}: {{item}}</li>
- </ul>
- </div>
- <script>
- var test = {name: "test"};
- var vm = new Vue({
- el: '#app',
- data: {
- items: {
- name: "wd",
- age: "27",
- sex: "man"
- }
- }
- })
- </script>
顯示內容為:
- name: wd
- age: 27
- sex: man
這個key也可以使用別名,方法很簡單,標簽如下寫:
- <li v-for="(a_key,item) in items" track-by="$index">{{a_key}}: {{item}}</li>
這里的a_key就相當於$key
且他們之間不會互相沖突,並能同時使用。
注意:別名對數組有效,$key對數組無效
⑩遍歷順序:
按照Object.keys()的結果遍歷
例如:
- var a = {a: 1, b: 2, c: 3};
- Object.keys(a)
其返回結果是:
- ["a", "b", "c"]
然后會按照這個順序來遍歷,但其結果可能會因為JavaScript引擎的不同而不同(受影響的是對象);
⑪v-for一個數字
可以對一個數字使用v-for,例如:
- <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都有效(都會被檢索),
如代碼:
- <div id="app">
- <input v-model="input"/>
- <p>請在輸入框內輸入內容,只會將符合條件的內容顯示出來</p>
- <ul>
- <li v-for="item in items|filterBy input">{{item}}</li>
- </ul>
- </div>
- <script>
- var test = {name: "test"};
- var vm = new Vue({
- el: '#app',
- data: {
- input: "",
- items: {
- name: "wd",
- age: "27",
- sex: "man"
- }
- }
- })
- </script>
注意:
(1)假如輸入‘a’,雖然name屬性和age屬性的值沒有a,但是其key有,所以依然會顯示;
(2)不能只對其值(如果v-for的是一個對象的話)過濾生效,比如
- <li v-for="item in items|filterBy input in 'item'">{{item}}</li>
是無效的寫法!
(3)如果要使用(2)中的方法,必須只能面對對象數組;
如以下:
- <div id="app">
- <input v-model="input"/>
- <p>請在輸入框內輸入內容,只會顯示name符合的</p>
- <ul>
- <li v-for="(key,item) in items|filterBy input in 'name'">age:{{item.age}},name:{{item.name}}</li>
- </ul>
- </div>
- <script>
- var test = {name: "test"};
- var vm = new Vue({
- el: '#app',
- data: {
- input: "",
- items: [
- {age: 1, name: "abc"},
- {age: 2, name: "ab"},
- {age: 3, name: "c"}
- ]
- }
- })
- </script>
(4)多字段過濾
如以下:
- <li v-for="(key,item) in items|filterBy input in 'name''age'">age:{{item.age}},name:{{item.name}}</li>
無論是age符合或者是name符合,都可以正常顯示。
(5)動態多字段過濾
- <div id="app">
- <input v-model="input"/>
- <p>請在輸入框內輸入內容,只會顯示name符合的</p>
- <ul>
- <li v-for="(key,item) in items|filterBy input in List">age:{{item.age}},name:{{item.name}}</li>
- </ul>
- <button @click="change">點擊搜索age</button>
- </div>
- <script>
- var test = {name: "test"};
- var vm = new Vue({
- el: '#app',
- data: {
- input: "",
- List: "name",
- items: [
- {age: 1, name: "abc"},
- {age: 2, name: "ab"},
- {age: 3, name: "c"}
- ]
- },
- methods: {
- change: function () {
- this.List = "age";
- }
- }
- })
- </script>
(1)初始過濾name,點擊按鈕過濾age;
(2)List可以是字符串,也可以是數組;
(3)動態改變依然會生效;
【4】orderBy
用於排序的過濾,可以加參數,參數>=0則為正序排序,<0則為倒序排序
普通寫法:
- <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
- <li v-for="(key,item) in items|orderBy 'name' -1"> age:{{item.age}},name:{{item.name}}</li>
根據name,倒序排列(因為參數為-1,其<0),字符串的排列順序為逐字母比較順序。
也可以使用函數作為排序條件,具體而言,如代碼:
- <div id="app">
- <input v-model="input"/>
- <p>請在輸入框內輸入內容,只會顯示name符合的</p>
- <ul>
- <li v-for="(key,item) in items|orderBy test">age:{{item.age}},name:{{item.name}}</li>
- </ul>
- <button @click="test">點擊搜索age</button>
- </div>
- <script>
- var test = {name: "test"};
- var vm = new Vue({
- el: '#app',
- data: {
- items: [
- {age: 5, name: "abc"},
- {age: 2, name: "ab"},
- {age: 13, name: "c"},
- {age: 33, name: "c"},
- {age: 3, name: "c"}
- ]
- },
- methods: {
- test: function (a, b) {
- return a.age - b.age;
- }
- }
- })
- </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