一. 和对象类似,数组也是引用类型,因此也存在比较复杂的侦听规则。从理论上说,修改一个数组的内容,比如修改数组中某个元素的值,或者给数组添加新的元素等,都不会修改数组本身的地址(引用),因此也不会被侦听到。为此,Vue.js 对数组做了特殊处理,使得使用标准的数组操作方法对数组所做的修改,都可以被侦听到。
1.使用标准方法修改数组可以被侦听到
当通过下列方法操作或更改数组时,变化可以被侦听到。这些方法包括:
· push( ) 尾部添加
· pop () 尾部删除
· unshift() 头部添加
·shift() 头部删除
·splice() 删除、添加、替换
·sort( ) 排序
·reverse() 逆序
通过push方法在数组array中添加一个新元素,这个变化可以被侦听到。
1 <script>
2 let vm = new Vue({
3 data:{
4 array:[0,1,2]
5 },
6 watch: {
7 array(newValue){
8 console.log(`array变化为${newValue}`);
9 }
10 }
11 });
12 vm.array.push(3);//可以被侦听到
13 </script>
2.替换数组可以被侦听到
1 <script>
2 let vm = new Vue({
3 data:{
4 array:[0,1,2]
5 },
6 watch: {
7 array(newValue){
8 console.log(`array变化为${newValue}`);
9 }
10 }
11 });
12 //替换为新数组,这可以被侦听到
13 vm.array = vm.array.filter(_=>_> 0);
14 </script>
3.无法被侦听的情况
由于受早期版本的 JavaScript(ES5)的限制,在 Vue 2中并不能侦听到数组的某些变化,包括全两种情况:
直接通过下标的方式来修改数组,例如 vm.items[5]=new Value。
直接通过修改数组的 length 属性的方式来修改数组,例如 vm.items.length=10。
除了上述这两种情况,我们还经常遇到的场景是:数组元素是一个对象,而我们改变的是数组元素的一个属性。
1 <script>
2 let vm = new Vue ({
3 data: {
4 array: [0,1,2,{x:1}]
5 },
6 watch:{
7 array(newValue){
8 console.log(newValue[2],newValue[3].x);
9 }
10 }
11 });
12 vm.array[2] =5; //修改数组元素本身
13 vm.array[3].x =10; //数组元素是对象,修改对象的属性
14 vm.array.length = 0; //通过 length 属性修改数组长度
15 </script>
在上面的代码中,这三种情况都无法被侦听到 解决方法如下:
(1)在实际开发中,通过 length 属性改变数组长度的情况很少见,基本上只要记住不要这样做就可以。如果需要改变数组长度,用上面介绍的几种操作数组的标准方法代替即可。
(2)对于需要修改数组的某个元素对象属性的情况,可以按照前面介绍的方法,把侦听器设为“深度侦听”的,就可以被侦听到了。
(3)对于直接修改数组元素的情况,可以使用 Vue.js 提供的$set(方法。
1 <script>
2 let vm = new Vue({
3 data:{
4 array:[0,1,2,{x:1}]
5 },
6 watch:{
7 array(newValue){
8 console.log(newValue[2] newValue[3].x);
9 }
10 }
11 });
12 vm.$set(vm.array,2,5); //修改元素
13 vm.$set(vm.array[3],'x',10 ); //修改元素的属性
14</script>
二. 总结
1. 如果使用了 push()等标准的数组操作方法, 那么可以被侦听到。
2. 如果彻底替换为一个新的数组,那么可以被侦听到。
3. 如果直接修改数组的元素,那么无法被侦呢听到,解决方法是使用$set ()方法修改元素的内容,只有这样才能被侦听到。
4.如果侦听器已通过“{deep:true}”设置为“深度侦听”的,那么当修改对象元素的属性时,可被侦听到。但是,如果是元素本身被修改,那么依然无法被侦听到。
5.如果侦听器没有被设置为“深度侦听”的,那么对象的属性可以用$set()方法来修改,从而实现此修改被侦听到的目的。
6.不要通过 length 属性来修改数组长度,而改用其他标准方法显示数组长度的变化。