【Vue原理】依存収集-ソース版の参照データ型


文章を書くのは容易ではない,ほめてくれないか.
Vueソースの共有に専念し、文章は白話版とソース版に分けられ、白話版は仕事の原理を理解し、ソース版は内部の詳細を理解するのに役立ち、一緒に勉強しましょう.
研究はVueバージョンに基づいて
【2.5.17】
レイアウトが悪いと思ったら、下のリンクをクリックするか、下に引いて公衆番号に注目してもいいでしょう.
【Vue原理】依存収集-ソース版の参照データ型
前回、基礎データ型の依存収集を分析しました
【Vue原理】依存収集-ソース版の基本データ型
この内容は、参照タイプのデータに対する依存収集分析です.参照タイプのデータは複雑で、別々に書かなければならないからです.
文章はとても长くて、高いエネルギーは警报して、准备をして心に耐えるのが良くて、きっと少し収获があります
しかし、二つのタイプのデータの処理は、また重複するところが多いので、違いのところだけを書けばいいと思います.そうしないと、くだらないことが多いように見えます.
2つのステップには、異なる点があります.
1、データ初期化
2、依存収集
データ初期化プロセス
データ型が参照型の場合、データの追加処理が必要です.
処理はまたオブジェクトと配列の2種類に分けられて、分けて言います
1オブジェクト
1、オブジェクトの各属性を遍歴し、同様に応答式を設定し、属性がすべて基本タイプであると仮定し、処理フローは前編と同じである.
2、データオブジェクトごとにob属性が追加される
たとえばchildのデータオブジェクトを設定する
次の図では、childオブジェクト処理後にobプロパティが追加されていることを示します.
ob_ 属性は何の役に立つの?
観察できますob__ 前の基礎データ型で述べたように、depプロパティがあります.
では、このob属性は何の役に立ちますか?
観察できますob__ 前の基礎データ型で述べたように、depプロパティがあります.
depはストレージ依存の場所です
例えばページがデータchildを参照し、watchがデータchildを参照すると、childはこの2つをdep.subsに保存します.
dep.subs = [   -watcher,watch-watcher ]

しかし、前編のベースタイプではdepは閉パッケージとして存在していたのでしょうか、何かに保存されているわけではありません
はい、これが参照タイプとベースタイプの違いです.
ベースデータ型は、「閉パケットdep」のみを使用して依存を格納します.
参照データ型は、「閉パケットdep」と「__ob_.dep」の2種類を使用して依存関係を格納します.
何?閉鎖depはどこだ?では、defineReactiveのソースコードでは、この方法のソースコードを見てみましょう.次は
では、なぜ、参照タイプを使用する必要があるのでしょうか.ob__.depストレージ依存は?
まず、記憶依存は、データが変化したときに依存を通知するためであることを明確にする.ob__.depも変化後のお知らせのため
閉パッケージdepはdefineReactiveのみ存在し、他の場所では使用できないため、別の場所で使用する必要があります.
他のどこで使うんですか?
Vueマウントプロトタイプ上のメソッドsetとdelでは、ソースコードは次のようになります.
function set(target, key, val) {    

    var ob = (target).__ob__;    

    //       
    ob.dep.notify();
}
Vue.prototype.$set = set;
function del(target, key) {    

    var ob = (target).__ob__;    

    delete target[key];    

    if (!ob)  return

    //       
    ob.dep.notify();

}
Vue.prototype.$delete = del;

この2つの方法は、オブジェクトにプロパティを動的に追加したり削除したりするために使用されたはずです.
しかし、直接属性を追加したり削除したりすると、Vueは次のように傍受できません.
child.xxxx=1

delete child.xxxx

だからVueで包装した方法setとdelで操作しなければなりません
setとdelの実行が完了すると、更新依存を通知する必要がありますが、どうやって通知しますか?
このとき、【_ob_.dep】が機能します!依存して1部多く集めましたob__.depで
使用は上記の一言で更新をお知らせします
ob.dep.notify();

2、配列
1、配列を巡回する必要があります.配列はオブジェクト配列である可能性があります.以下のように.
[{name:1},{name:888}]

遍歴は、サブアイテムがオブジェクトである場合、上の解析オブジェクトと同様に操作されます.
2、配列にob属性を保存する
例えばarr配列を設定する
arr配列にobプロパティが追加されているのを見ました
実はこのob属性と前の話の対象の作用は多くなくて、ここでもただ_を言いますob__.dep
配列内の_ob__.depストレージも依存していますが、誰に使いますか?
Vueパッケージの配列メソッドに使用するには、配列の変化も傍受するには、Vueパッケージの配列メソッドを使用する必要があることを知っておく必要があります.そうしないと、リアルタイムで更新できません.
ここでウエイトリフティングの書き方の一つであるpush、その他にspliceなど、Vue公式文書で説明されています
var original = Array.prototype.push;

Array.prototype.push = function() {    

    var args = [],

    len = arguments.length;    

    //       push       
    while (len--) args[len] = arguments[len];

    //       
    var result = original.apply(this, args);    

    var ob = this.__ob__;    

    // notify change
    ob.dep.notify();    

    return resul
}

配列メソッドを実行した後も、依存更新、すなわち通知__を通知する必要があることを示します.ob__.depで収集された依存性の更新
応答型データが参照タイプに対してどのような追加の処理を行ったのか,主にob属性を追加したのかが分かった.
私たちはすでにobが何の役に立つかを知っていて、今ソースコードがどのようにobを追加するかを見てみましょう
//    Vue     

function initData(vm) {    

    var data = vm.$options.data;

    data = vm._data = 

        typeof data === 'function' ? 

        data.call(vm, vm) : data || {};

    ....   data      key ,    ,    
    observe(data, true);

}

function observe(value) {    

    if (Array.isArray(value) || typeof value == "object") {
        ob = new Observer(value);
    }    
    return ob
}
function Observer(value) {   

    //           
    this.dep = new Dep();   

    //               __ob__   ,   Observer   
    value.__ob__ = this

    if (Array.isArray(value)) { 

        //     ,         observe   ,         __ob__
        for (var i = 0, l =value.length; i < l; i++) {
            observe(value[i]);
        }

    } else {        

        var keys = Object.keys(value);     

        //               
        for (var i = 0; i < keys.length; i++) {
            defineReactive(value, keys[i]);
        }
    }
};

ソースコードの流れは次のように悪くありませんが、参照データ型を処理すると、ソースコードの追加処理が数行増加します.
以前は、次のようなオブジェクトデータ型について説明しました.
複数のオブジェクトがネストされている場合は?例えば、どうやって処理しますか.
そう、Vueは再帰的に処理され、属性を巡回してdefineReactive処理を使用すると、再帰的にobserve処理を呼び出す(ソースラベルが赤に太くなる)
値がオブジェクトの場合、同じように値にobを1つ追加します.
そうでない場合は、通常下に進み、応答式を設定します.
ソースコードは以下の通りです.
function defineReactive(obj, key, value) {  

    // dep                
    var dep = new Dep();    
    var val  = obj[key] 

    //     childOb     Observer   
    //         ,        
    var childOb = observe(val);    

    Object.defineProperty(obj, key, {
        get() {...          ,    },
        set() { .... }
    });
}

参考までにフローチャートを描く
ハハハ、上は长いですね、少しですが、仕方がありません.详しく言いたいですね.いいでしょう.まだ一段ありますが、短いですね.ハハハ、どうせ読み终わった人は、私はjioがすごいです.承知します.もしあなたがよく読んだら、コメントしてくれませんか.誰かがよく読んでいることを知らせてください.
依存収集プロセス
収集プロセスは、Objectに重点を置くことです.defineProperty設定のgetメソッド
ベースタイプのデータと比較すると、参照タイプの収集方法も数行の処理が多くなっただけで、違いは2行のコードです.
childOb.dep.depend、私に簡単にchildObに変えられました.dep.addSub(Dep.target)dependArray(value)は、次のようにソースコードを先に見ることができます.
function defineReactive(obj, key, value) {    

    var dep = new Dep();    
    var val  = obj[key]    
    var childOb = observe(val);    

    Object.defineProperty(obj, key, {
        get() {            
            var value = val            
            if (Dep.target) {

                //       dep.subs
                dep.addSub(Dep.target);

                //         ,Observer     dep        
                if (childOb) {
                    childOb.dep.addSub(Dep.target)          
                    if (Array.isArray(value)) {
                        dependArray(value);
                    }
                }
            }            
            return value
        }
    });
}

上のソースコードは、オブジェクトと配列の処理が混ざっています.
1、対象
データ初期化のプロセスでは、値がオブジェクトであることがわかっていれば、依存関係が複数格納されます.ob__.depで
たった一言
childOb.dep.depend();

配列にはもう一つの処理があります
dependArray(value);

ソースコードを見て、次のようにします.
function dependArray(value) {    

    for (var i = 0, l = value.length; i < l; i++) {        

        var e = value[i];        

        //           ,      dep.subs
        e && e.__ob__ && e.__ob__.dep.addSub(Dep.target);   
     

        //          ,        
        if (Array.isArray(e)) {
            dependArray(e);
        }
    }
}

明らかに、配列の中にオブジェクトがあることを防止するために、配列のサブオブジェクトにも1部保存する必要があります.
なぜサブオブジェクトも依存を保存するのかと聞かれるに違いありません.
1、ページは配列に依存して、配列のサブアイテムが変化して、ページも更新する必要がありますか?しかし、サブアイテムの内部変化はどのようにページの更新を通知しますか?サブオブジェクトにも依存を保存する必要がありますか?
2、配列サブアイテム配列の変化、すなわちオブジェクトの削除属性であり、Vueパッケージメソッドsetとdelを使用する必要があり、setとdelは依存更新を通知するので、サブアイテムオブジェクトも保存する
くりを見る
ページテンプレート
配列のデータを見ると2つのobが存在する
まとめ
ここまで来ると,参照タイプとベースタイプの処理の違いが明らかになる.
1、参照タイプが1つ増えます_ob__収集された依存関係を格納するdepを含むプロパティ
2、オブジェクト使用_ob__.dep、Vueカスタムメソッドsetとdelに作用する
3、配列使用_ob__.depは、Vue書き換えの配列方法pushなどに作用する
やっと書き終わって、本当に長いですが、価値があると思います.