添加一个爱好(hobby:[]
)
> vm._data
< {__ob__: Observer}
address: (...)
name: (...)
student: Object
friends: (...)
hobby: Array(3)
0: "玩游戏"
1: "看动漫"
2: "看直播"
length: 3
没有找到为数组服务的get
和set
由于你把hobby
写成了一个数组,它并没有为数组里的某一个元素去匹配get
和set
, 如果没有为0
,1
服务的get
,set
那也就意味着某一天你通过这个0索引值去改变"玩游戏"的时候,数据能改掉但是Vue
监测不到,也不会引起页面的更新;名字一改就会引起set name(val)
就调,就重新解析模板后续的动作都开始执行,但是由于你爱好里面想改掉"玩游戏",它没有与之对应的set
> vm._data.student.hobby[0] = '学习'
< '学习'
> vm._data.student.hobby
< (3) ['学习', '看动漫', '看直播', __ob__: Observer]
改了,但是vue不知道你改了, vue里面数组的监视不是靠get
和set
是靠
Vue的作者是这么想的:程序员里有一个数组(let arr = [1,3,5,7]
)程序员想要修改这个数组有可能调用哪些方法呢?
你想往数组里最后一个位置新增一个元素:push
想删除最后一个元素:pop
想删除第一个元素:shift
想往前面加一个:unshift
splice
想在数组中间插入一个元素
在指定位置删除一个元素
或者替换掉指定位置的某个元素
想为数组进行一个排序:sort
想反转这个数组:reverse
以上的方法都是可以修改数组的
filter
因为不会影响原数组的改变,既然不能影响原数组的改变,那vue怎么知道你改了数组呢?
添加一个爱好
> vm._data.student.hobby.push('学习')
< 4
删除第一个爱好
> vm._data.student.hobby.shift()
< '玩游戏'
替换调第一个爱好
> vm._data.student.hobby.splice(0,1,'打台球')
< ['看动漫']
0: "看动漫"
length: 1
[[Prototype]]: Array(0)
splice中
0:第一个元素,也就是大于等于0
1:也就是小于1的
‘打台球’:替换的信息
Vue是怎么知道这些方法的?
它用了一个技术,叫’包装’
你是不是找到了一个数组,叫
vm._data.student.hobby
你是不是调了这个push()
就你所调用的这个push()
已经不是数组身上最原汁原味的那个push
,说白了就是说不是数组原型对象上的push了(Array.prototype.push()
)
arr身上没有push
沿着原型(Prototype
)找
> vm._data
< {__ob__: Observer}
address: (...)
name: (...)
student: Object
friends: (...)
hobby: Array(3)
0: "玩游戏"
1: "看动漫"
2: "看直播"
length: 3
__ob__: Observer {value: Array(3), dep: Dep, vmCount: 0}
[[Prototype]]: Array
pop: ƒ mutator()
push: ƒ mutator()
reverse: ƒ mutator()
shift: ƒ mutator()
sort: ƒ mutator()
splice: ƒ mutator()
unshift: ƒ mutator()
所以我们可以验证一下一个事情
```Console
> arr.push === Array.prototype.push
< true
我们可以照样验证:
> vm._data.student.hobby.push === Array.prototype.push
< false
这个hobby
数组被vue
管理了,你调用的push
不再是原型对象上的push
了
先找到的是vue
写的这个push
,给你做了俩件事:
- 1、规规矩矩的给你调了原型的
push
(Array.prototype.push
) - 2、重新解析模板生成虚拟DOM那一套流程
Vue对数组的监测其实是靠包装数组身上的常用修改数组的方法所实现的
请看官网
其实还有一个方法改变数组
> Vue.set(vm._data.student.hobby,0,'学习')
< '学习'
> vm.$set(vm._data.student.hobby,0,'学习')
< '学习'
注:Vue.set和vm.$set里第一个元素target不能是vm本身和vm源数据
使用数据代理写法
> vm.student.hobby.push('学习')
< 4