Vue 数组更新与排序过滤
前面的话Vue 的核心是数据与视图的双向绑定,当我们修改数组时,Vue会检测到数据变化,所以用v-for渲染的视图也会立即更新。Vue为了增加列表渲染的功能,增加了一组观察数组的方法,而且可以显示一个数组的过滤或排序的副本。这篇文章将介绍Vue数组更新及过滤排序。变异方法Vue包含了一组观察数组变异的方法,使用它们改变数组也会触发视图更新。●push()接受任意数量的参数,把...
前面的话
Vue 的核心是数据与视图的双向绑定,当我们修改数组时,Vue会检测到数据变化,所以用v-for 渲染的视图也会立即更新。Vue为了增加列表渲染的功能,增加了一组观察数组的方法,而且可以显示一个数组的过滤或排序的副本。这篇文章将介绍Vue数组更新及过滤排序。
变异方法
Vue包含了一组观察数组变异的方法,使用它们改变数组也会触发视图更新。
● push() 接受任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。
● pop() 从数组末尾移除最后一项,减少数组的length值,然后返回移除的项
● shift() 移除数组中的第一个项并返回该项,同时数组的长度减1
● unshift() 在数组前端添加任意一个项并返回新数组长度
● splice() 删除原数组的一部分成员,并可以在被删除的位置添加新的数组成员
● sort() 调用每个数组的toString()方法,然后比较得到的字符串排序,返回经过排序之后的数组。
● reverse() 用于反转数组的顺序,返回经过排序之后的数组
<div id="app1">
<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>
new Vue({
el: "#app1",
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>
非变异方法
使用以上方法会改变调用这些方法调用的原始数组,但有些方法不会改变原数组。
● concat() 先创建当前数组的副本,然后将接受到的参数添加到这个副本的末尾,最后返回新构建的数组
● slice() 基于当前数组中一个或多个项创建一个新数组,接受一个或两个参数,即要返回项的起始和结束位置 最后返回新数组。
● map() 对数组的每一项运行给定的函数,返回每次函数调用的结果组成的数组
● filter() 对数组中的每一项运行给定函数,该函数会返回true的项组成的数组
<div id="app2">
<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>
new Vue({
el: "#app2",
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元素。替换的数组中, 含有相同元素的项不会被重新渲染,因此可以大胆地用新数组来替换旧数组,不用担心性能问题。
无法检测
由于js的限制,Vue不能检测以下变动的数组,视图也不会更新:
1: 利用索引直接设置一个项时,例如: vm.items[indexOfItem] = newValue
2: 修改数组的长度时,例如:vm.items.length = newLength
<div id="app3">
<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 vm = new Vue({
el: '#app3',
data: {
items: ["foo","Bar","Baz"],
message: ''
},
watch: {
items: watchFunc = function() {
this.message = '数据发生变化';
var that = this;
setTimeout(function() {
that.message = '';
},500);
}
},
methods: {
pop() {
this.items.pop();
},
setVal() {
this.items[0] = 'match';
},
setLength() {
this.items.length = 2;
}
}
})
</script>
可以看到点击前面两个按钮没有变化,即直接设置值和长度watch不能监听到其变化
如何解决这两个问题?
有两种方法都可以实现vm.items[indexOfItem] = newValue相同的效果,同时也触发状态更新。
1: 使用Vue内置的方法set
Vue.set(vm.items, indexOfItem, newValue)
2:使用splice方法
vm.items.splice(indexOfItem, 1 ,newValue)
解决第二类问题,也可以直接使用splice
vm.items.splice(newLength)
<div id="app4">
<div>
<button @click='setVal1'>setVal1</button>
<button @click='setVal2'>setVal1</button>
<button @click='setLength'>setLength</button>
</div>
<ul>
<li v-for="item in items">
{{ item }}
</li>
</ul>
<p>{{message}}</p>
</div>
<script>
new Vue({
el: "#app4",
data: {
items: ['Foo','Bar', 'Baz'],
message: ''
},
watch: {
items: watchFunc = function(){
this.message = "数据发生变化";
var that = this;
setTimeout(function() {
that.message = '';
},500);
}
},
methods: {
setVal1() {
Vue.set(this.items, 0, 'match');
},
setVal2() {
this.items.splice(1, 1, 'xiaoqi');
},
setLength() {
this.items.splice(2);
// 删除第三个元素
}
}
})
</script>
过滤与排序
当你不想改变原数组,想通过一个数组的副本来做过滤或排序的显示时,可以使用计算属性来返回 过滤或排序后的数组。
实例1:
<div id="app5">
<ul>
<li v-for="n in Numbers">
{{n}}
</li>
</ul>
</div>
<script>
new Vue({
el: '#app5',
data: {
numbers: [ 1, 2, 3, 4, 5 ],
},
computed: {
Numbers: function() {
return this.numbers.filter(function (item) {
return item % 2 === 0;
})
}
}
})
</scripit>
上例中把是2的倍数的数据过滤出来,计算属性Numbers依赖numbers,但是不会修改numbers
实例2:
<div id="app6">
<ul>
<template v-for="book in filterBooks">
<li>书名: {{ book.name }}</li>
<li>作者: {{ book.author }}</li>
</template>
</ul>
</div>
<script>
new Vue({
el: "#app6",
data: {
books: [
{
name: '<< JavaScript高级程序设计>>',
author: 'Nicholas'
},
{
name: '<< JavaScript语言精粹>>',
author: 'Douglas Crockford'
},
{
name: "<< 深入理解ES6>>",
author: '阮一峰'
}
]
},
computed: {
filterBooks: function() {
return this.books.filter(function (item) {
return item.name.match(/JavaScript/);
})
},
}
})
</script>
上例中把书名中包含JavaScript 的数据过滤出来,计算属性filterBooks依赖 books,但是不会修改 books.
更多推荐
所有评论(0)