參考版本 vue源碼版本:0.11
相關vue
vue實現雙向數據綁定的關鍵是 Object.defineProperty ,讓咱們先來看下這個函數。git
在MDN上查看有關 Object.defineProperty 的解釋。github
咱們先從最簡單的開始:app
let a = {'b': 1}; Object.defineProperty(a, 'b', { enumerable: false, configurable: false, get: function(){ console.log('b' + '被訪問'); }, set: function(newVal){ console.log('b' + '被修改,新' + 'b' + '=' + newVal); } }); a.b = 2; // b被修改,新b=2 a.b; // b被訪問
這樣,咱們就能監聽對象了!但問題並不單單這麼簡單。。。函數
咱們可能會有對象中屬性的值仍是對象這種嵌套狀況,能夠經過遞歸解決!this
在vue源代碼文件 srcobserveobserver.js 中prototype
// 觀察者構造函數 function Observer(data){ this.data = data; this.walk(data); } let p = Observer.prototype; p.walk = function(obj){ let val; for(let key in obj){ // 經過 hasOwnProperty 過濾掉一個對象自己擁有的屬性 if(obj.hasOwnProperty(key)){ val = obj[key]; // 遞歸調用 循環全部對象出來 if(typeof val === 'object'){ new Observer(val); } this.convert(key, val); } } }; p.convert = function(key, val){ Object.defineProperty(this.data, key, { enumerable: false, configurable: false, get: function(){ console.log(key + '被訪問'); }, set: function(newVal){ console.log(key + '被修改,新' + key + '=' + newVal); if(newVal === val) return ; val = newVal; } }) }; let data = { user: { name: 'zhangsan', age: 14 }, address: { city: 'beijing' } } let app = new Observer(data); data.user.name; // user被訪問