Vue2.0中的响应式处理(数据改变视图改变)的核心是Object.definedProperty。vue
data中的变量才是响应式变量,但对于对象类型的变量,给其添加新的属性或删除属性时,视图不能响应到值的变化;对于数组类型的变量,经过数组下标修改属性值,视图不是不能响应到值的变化,经过push、pop、splice等方法修改数组的值,视图可以响应值的变化。为何是这样的规则?先从Object.definedProperty的使用规则开始提及。segmentfault
一、给{}类型对象的属性从新定义规则数组
function defineReactive(obj, key, val) { Object.defineProperty(obj, key, { enumerable: true, // 可枚举 configurable: true, // 可写 get: function() { console.log('get'); return val; }, set: function(newVal) { // 设置时,能够添加相应的操做 console.log('set:', val); val += newVal; } }); } let obj = {name: '成龙大哥', say: ':其实我以前是拒绝拍这个游戏广告的,'}; Object.keys(obj).forEach(k => { defineReactive(obj, k, obj[k]); }); obj.say = '后来我试玩了一下,哇,好热血,蛮好玩的'; //会触发set obj.age = 20 //不会触发set console.log(obj.name + obj.say, obj);
对于新增的对象属性不会触发set方法。函数
二、给数组[]类型对象的属性从新定义规则性能
function defineReactive(obj, key, val) { Object.defineProperty(obj, key, { enumerable: true, // 可枚举 configurable: true, // 可写 get: function() { console.log('get'); return val; }, set: function(newVal) { // 设置时,能够添加相应的操做 console.log('set:', val); val += newVal; } }); } let arr = [1,2,3,4,5]; arr.forEach((v, i) => { defineReactive(arr, i, v); }); arr[0] = 'oh nanana'; // 触发set arr.push(6) // 不会触发set console.log(arr) let arr2 = [{name: '1'},{name: '2'}, {name: '3'}]; arr2.forEach((v, i) => { defineReactive(arr2, i, v); }); arr2.forEach((v, i) => { v.status= true // 不会触发set }); arr2.forEach((v, i) => { v.name = true // 不会触发set }); arr2[0] = {name: 2} // 会触发set arr2.splice(1,1,{name: 111}) // 会触发set arr2.push({name: 'tt'}) // 不会触发set arr2.length = 2 // 不会触发set
初始化时会将data中的值经过defineProperty设置为响应式,当给变量赋值时就会触发变量对应的set方法,从而调用视图更新的函数。spa
这里要说的是Object.definedProperty是能够经过数组下标修改值以后触发对应的set方法的,经过push、pop等方法修改数组的值以后是不会触发set方法。code
可是Vue中考虑到性能问题,对于数组类型的数据改变本身定义了一套触发响应的规则,经过数组下标修改数组的值是不会触发视图更新的,可是经过push、pop、shift、unshift等方法修改数组的值是能够触发视图更新的。对象
Vue官方说法不会触发视图更新的状况:blog
一、对于数组对象游戏
二、对于{}对象
默认的Object.definedProperty中,对于操做数组的方法,默认只有利用数组中的splice修改数组值时能够触发set(splice(1, 1, value), 至关于经过数组下标修改属性值)。
但由于Vue作了处理,如下变异方法修改数组的值均可以触发视图的更新。
vue究竟对数组如何作的处理呢?见下一节
参考资料: