Vue爲了增長列表渲染的功能,增長了一組觀察數組的方法,並且能夠顯示一個數組的過濾或排序的副本。本文將詳細介紹Vue數組更新及過濾排序html
Vue 包含一組觀察數組的變異方法,它們將會觸發視圖更新,包含如下方法前端
push() 接收任意數量的參數,把它們逐個添加到數組末尾,並返回修改後數組的長度
pop() 從數組末尾移除最後一項,減小數組的length值,而後返回移除的項
shift() 移除數組中的第一個項並返回該項,同時數組的長度減1
unshift() 在數組前端添加任意個項並返回新數組長度
splice() 刪除原數組的一部分紅員,並能夠在被刪除的位置添加入新的數組成員
sort() 調用每一個數組項的toString()方法,而後比較獲得的字符串排序,返回通過排序以後的數組
reverse() 用於反轉數組的順序,返回通過排序以後的數組
<div id="example"> <div> <button @click='push'>push</button> <button @click='pop'>pop</button> <button @click='shift'>shift</button> <button @click='unshift'>unshift</button> <button @click='splice'>splice</button> <button @click='sort'>sort</button> <button @click='reverse'>reverse</button> </div> <ul> <li v-for="item in items" > {{ item.message }} </li> </ul> </div>
<script> var example = new Vue({ el: '#example', data: { items: [ {message: 'Foo' }, {message: 'Bar' }, {message: 'Baz' } ], addValue:{message:'match'} }, methods:{ push(){ this.items.push(this.addValue) }, pop(){ this.items.pop() }, shift(){ this.items.shift() }, unshift(){ this.items.unshift(this.addValue) }, splice(){ this.items.splice(0,1) }, sort(){ this.items.sort() }, reverse(){ this.items.reverse() }, } }) </script>
變異方法(mutation method),顧名思義,會改變被這些方法調用的原始數組。相比之下,也有非變異(non-mutating method)方法,例如: filter()
, concat()
, slice()
。這些不會改變原始數組,但老是返回一個新數組。當使用非變異方法時,能夠用新數組替換舊數組vue
concat() 先建立當前數組一個副本,而後將接收到的參數添加到這個副本的末尾,最後返回新構建的數組
slice() 基於當前數組中一個或多個項建立一個新數組,接受一個或兩個參數,即要返回項的起始和結束位置,最後返回新數組
map() 對數組的每一項運行給定函數,返回每次函數調用的結果組成的數組
filter() 對數組中的每一項運行給定函數,該函數會返回true的項組成的數組
<div id="example"> <div> <button @click='concat'>concat</button> <button @click='slice'>slice</button> <button @click='map'>map</button> <button @click='filter'>filter</button> </div> <ul> <li v-for="item in items" > {{ item }} </li> </ul> </div>
<script> var example = new Vue({ el: '#example', data: { items: ['Foo','Bar','Baz'], addValue:'match' }, methods:{ concat(){ this.items = this.items.concat(this.addValue) }, slice(){ this.items = this.items.slice(1) }, map(){ this.items = this.items.map(function(item,index,arr){ return index + item; }) }, filter(){ this.items = this.items.filter(function(item,index,arr){ return (index > 0); }) } } }) </script>
以上操做並不會致使Vue丟棄現有DOM並從新渲染整個列表。Vue實現了一些智能啓發式方法來最大化DOM元素重用,因此用一個含有相同元素的數組去替換原來的數組是很是高效的操做數組
因爲JS的限制, Vue 不能檢測如下變更的數組:函數
一、利用索引直接設置一個項時,例如: vm.items[indexOfItem] = newValue
this
二、修改數組的長度時,例如: vm.items.length = newLength
spa
<div id="example"> <div> <button @click='setVal'>setVal</button> <button @click='setLength'>setLength</button> <button @click='pop'>pop</button> </div> <ul> <li v-for="item in items" >{{ item }}</li> </ul> <p>{{ message }}</p> </div>
<script> var watchFunc = function(){ example.message = '數據發生變化'; setTimeout(function(){ example.message = ''; },500); } var example = new Vue({ el: '#example', data: { items: ['Foo','Bar','Baz'], message:'', }, watch:{ items:watchFunc }, methods:{ pop(){ this.items.pop() }, setVal(){ this.items[0]= 'match'; }, setLength(){ this.items.length = 2; } } }) </script>
以上代碼中,直接設置值和長度使用watch不能檢測到變化prototype
如下兩種方式均可以實現和vm.items[indexOfItem]=newValue
相同的效果, 同時也將觸發狀態更新code
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)
爲了解決第二類問題,可使用 splice
htm
example1.items.splice(newLength)
<div id="example"> <div> <button @click='setVal1'>setVal1</button> <button @click='setVal2'>setVal2</button> <button @click='setLength'>setLength</button> </div> <ul> <li v-for="item in items" >{{ item }}</li> </ul> <p>{{ message }}</p> </div>
<script> var watchFunc = function(){ example.message = '數據發生變化'; setTimeout(function(){ example.message = ''; },500); } var example = new Vue({ el: '#example', data: { items: ['Foo','Bar','Baz'], message:'', }, watch:{ items:watchFunc }, methods:{ setVal1(){ Vue.set(this.items, 0, 'match') }, setVal2(){ this.items.splice(1, 1, 'xiaohuochai') }, setLength(){ this.items.splice(2) } } }) </script>
有時,要顯示一個數組的過濾或排序副本,而不實際改變或重置原始數據。在這種狀況下,能夠建立返回過濾或排序數組的計算屬性
【computed】
<div id="example"> <ul> <li v-for="n in evenNumbers">{{ n }}</li> </ul> </div>
<script> var example = new Vue({ el: '#example', data: { numbers: [ 1, 2, 3, 4, 5 ], }, computed: { evenNumbers: function () { return this.numbers.filter(function (number) { return number % 2 === 0 }) } } }) </script>
【methods】
在計算屬性不適用的狀況下 (例如,在嵌套 v-for
循環中) 可使用一個 method 方法
<div id="example"> <ul> <li v-for="n in even(numbers)">{{ n }}</li> </ul> </div>
<script> var example = new Vue({ el: '#example', data: { numbers: [ 1, 2, 3, 4, 5 ], }, methods: { even: function (numbers) { return numbers.filter(function (number) { return number % 2 === 0 }) } } }) </script>