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究竟對數組如何作的處理呢?見下一節
參考資料: