參考版本 vue源碼版本:0.11
相干
vue完成雙向數據綁定的關鍵是 Object.defineProperty ,讓我們先來看下這個函數。
在MDN上檢察有關 Object.defineProperty 的詮釋。
我們先從最簡樸的最先:
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被接見
如許,我們就能夠監聽對象了!但題目並不僅僅這麼簡樸。。。
我們能夠會有對象中屬性的值照樣對象這類嵌套狀況,能夠經由過程遞歸處理!
在vue源代碼文件 srcobserveobserver.js 中
// 觀察者組織函數
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被接見