vueダイナミックデータバインド1--オブジェクトの変化をリスニングする方法

5863 ワード

以前はVueをよく使っていましたが、それだけでは満足していませんでした.内部実装の原理を知りたいので、ソースコードを勉強してみました.動的データバインディングはVueの最も基礎であり、最も有用な機能である.任意のオブジェクトを指定し、プロパティの読み取りと変更をどのように監視しますか?すなわち,プログラムがオブジェクトのどの属性にアクセスし,どの属性を変更したかをどのように知るか.例を挙げる.
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を実現するには、以下のような要求がある.
  • 入力パラメータはオブジェクトのみを考慮し、配列は考慮しない.
  • new Observerは、渡されたオブジェクトにdata属性がアクセスできるオブジェクトを返します.
  • dataで属性にアクセスし、設定した場合、対応する情報を印刷できます.
  • 入力パラメータオブジェクトが「比較的深い」オブジェクト(つまり、その属性値がオブジェクトである可能性もある)である場合、どうすればいいですか.

  • 上記の目標を達成するには、まずオブジェクトの構造関数を定義し、次にプロトタイプメソッドを定義し、オブジェクト自体の各プロパティを遍歴し、各プロパティに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);
    
  • アクセスした属性が1つのオブジェクトである場合、そのオブジェクト属性に対してnew Observerを行い、最下層の属性位置に到達するまで「深層」の属性もアクセスできるようにする.
  • 同時にオブジェクトにsetterを設定する場合、新しい値がオブジェクトであればnew Observerも続け、最下層の属性位置に達するまで、新しく設定した値オブジェクトのサブ属性もgetterとsetterに応答し続けることができます.効果は次のとおりです:
  • 上図に示すように、単純な値にアクセスしても、深いオブジェクトにアクセスしても、getterとsetterによく応答できます.