vueダイナミックデータバインド1--オブジェクトの変化をリスニングする方法
5863 ワード
以前はVueをよく使っていましたが、それだけでは満足していませんでした.内部実装の原理を知りたいので、ソースコードを勉強してみました.動的データバインディングはVueの最も基礎であり、最も有用な機能である.任意のオブジェクトを指定し、プロパティの読み取りと変更をどのように監視しますか?すなわち,プログラムがオブジェクトのどの属性にアクセスし,どの属性を変更したかをどのように知るか.例を挙げる.
このようなObserverを実現するには、以下のような要求がある.入力パラメータはオブジェクトのみを考慮し、配列は考慮しない. new Observerは、渡されたオブジェクトにdata属性がアクセスできるオブジェクトを返します. dataで属性にアクセスし、設定した場合、対応する情報を印刷できます. 入力パラメータオブジェクトが「比較的深い」オブジェクト(つまり、その属性値がオブジェクトである可能性もある)である場合、どうすればいいですか.
上記の目標を達成するには、まずオブジェクトの構造関数を定義し、次にプロトタイプメソッドを定義し、オブジェクト自体の各プロパティを遍歴し、各プロパティにgetメソッドとsetメソッドをバインドします.4つ目の問題を考慮して,プログラムに再帰的な考え方を加えた.実装コードは次のとおりです.アクセスした属性が1つのオブジェクトである場合、そのオブジェクト属性に対してnew Observerを行い、最下層の属性位置に到達するまで「深層」の属性もアクセスできるようにする. 同時にオブジェクトにsetterを設定する場合、新しい値がオブジェクトであればnew Observerも続け、最下層の属性位置に達するまで、新しく設定した値オブジェクトのサブ属性もgetterとsetterに応答し続けることができます.効果は次のとおりです: 上図に示すように、単純な値にアクセスしても、深いオブジェクトにアクセスしても、getterとsetterによく応答できます.
let app1 = new Observer({
name: 'yyy',
age: 20
});
let app2 = new Observer({
university: 'uestc',
major: 'computer'
});
// :
app1.data.name // name
app.data.age = 100; // age, 100
app2.data.university // university
app2.data.major = 'science' // major, science
このようなObserverを実現するには、以下のような要求がある.
上記の目標を達成するには、まずオブジェクトの構造関数を定義し、次にプロトタイプメソッドを定義し、オブジェクト自体の各プロパティを遍歴し、各プロパティにgetメソッドとsetメソッドをバインドします.4つ目の問題を考慮して,プログラムに再帰的な考え方を加えた.実装コードは次のとおりです.
//
function Observer(data){
this.data=data;
this.walk(data);
}
// walk()
//
// get set
Observer.prototype.walk = function(obj){
let val;
for(let key in obj){
// hasOwnProperty ?
// for...in 、
// hasOwnProperty true
// , 。
if(obj.hasOwnProperty(key)){
val = obj[key];
// , , new Observer,
if(typeof val ==='object'){
new Observer(val);
}
this.convert(key,val);
}
}
};
// get set
Observer.prototype.convert = function(key,val){
Object.defineProperty(this.data,key,{
enumerable:true,
configurable:true,
get:function(){
console.log(' '+key);
return val;
},
set:function(newVal){
console.log(' '+key);
console.log(' '+key+'='+newVal);
if(newVal===val) return;
// , new Observer,
if(typeof newVal === "object"){
new Observer(newVal);
};
val = newVal;
}
})
};
let data={
user:{
name: "yjm",
age: "21"
},
address: " "
};
let app =new Observer(data);