インタビュアーは、vue双方向データバインディングについて私に尋ねました、私は彼と1時間話すことができます[推奨コレクション]

はじめに:
インタビューでは、Vueの双方向データバインディングはどのように機能するのかとよく聞かれます。または、vueのソースコードを詳細に分析していて、その双方向データバインディングがどのように実装されているかを理解したい場合は、この記事で説明します。

一つは、実現原理

Vueデータの双方向バインディングは、パブリッシャー-サブスクライバーモデルと組み合わせたデータハイジャックによって実現されます。
ここに写真の説明を挿入これが上のビューです。原則として、ビューレイヤーのデータが変更されるとデータが更新され、データが変更されるとビューが更新されます。

詳細なプロセスは次のとおりです。

1.データが変更されると、Object.defineProperty()メソッドのsetメソッドを介して監視および更新し、データとビューの関係を定義するコールバック関数を呼び出して、ビューにデータの変更を通知し、ビュービューを実現します。変化する。

2.ビューが変更された場合、データ応答の変更は、基になる入力イベントを介して行われます。

第二に、実現プロセス

1.最下層の入力イベントを介してデータの応答を変更できる限り、ビュー層のビューを変更する方が簡単です。

2.主な問題は、データがいつ変更されたかを検出する方法と、ビューレイヤーのデータを変更する方法です。

最初に写真を見てみましょう。
ここに写真の説明を挿入データ更新ビューの難しさは、データが変更されたことを知る方法です。データが変更されたことを知っている限り、次のことは簡単に処理できます。Object.defineProperty()を使用してset関数をプロパティに設定している限り、この関数はデータが変更されたときにトリガーされ、ビューをデータで更新できます。

これで、vueの双方向バインディングを実装するには、最初にデータをハイジャックして監視する必要があることがわかったため、すべてのデータを監視するリスナーオブザーバーを設定する必要があります。データが変更された場合は、サブスクライバーWatcherにデータを更新する必要があるかどうかを確認するように指示する必要があります。サブスクライバーが多いため、これらのサブスクライバーを収集し、リスナーオブザーバーとサブスクライバーウォッチャーの間で統合管理を実行するには、メッセージサブスクライバーDep(コンテナー)が必要です。したがって、次に、次の2つの手順を実行して、双方向のデータバインディングを実現します。

1.リスナーオブザーバーを実装して、すべてのデータをハイジャックおよび監視し、変更がある場合はサブスクライバーに通知します。

2.プロパティの変更の通知を受信し、対応する機能を実行してビューを更新できるサブスクライバーウォッチャーを実装します。

フローチャートは次のとおりです。
ここに写真の説明を挿入

1.オブザーバーを実装する

function mvvm(data, key, val) {
    
    
    observe(val); 
    Object.defineProperty(data, key, {
    
    
        get: function() {
    
    
            return val;
        },
        set: function(newVal) {
    
    
            val = newVal;
        }
    });
}
 
function observe(data) {
    
    
	// 如果data不是对象,或者为空就不用观察
    if (!data || typeof data !== 'object') {
    
    
        return;
    }
    // 对每一个data对象都设置观察,可以执行get和set函数
    Object.keys(data).forEach(function(key) {
    
    
        mvvm(data, key, data[key]);
    });
};

2.depメッセージサブスクライバーとサブスクライバーを実装します

function mvvm(data, key, val) {
    
    
    observe(val); 
    var dep = new Dep(); 
    Object.defineProperty(data, key, 
        get: function() {
    
    
            if (Dep.self) {
    
    .  // 判断是否需要添加订阅者
                dep.additem(Dep.self); // 在这里添加一个订阅者
            }
            return val;
        },
        set: function(newVal) {
    
    
            if (val === newVal) {
    
    
                return;
            }
            val = newVal;
            dep.notify(); // 如果数据变化,通知所有订阅者
        }
    });
}
 
function Dep () {
    
    
	// 这里的消息订阅是可以是一个数组
    this.items = [];
}
Dep.prototype = {
    
    
    addItem: function(item) {
    
    
        this.items.push(item);
    },
    notify: function() {
    
    
        this.items.forEach(function(item) {
    
    
            item.update();
        });
    }
};
// 订阅者
function Watcher(_this, key, fun) {
    
    
    this.fun = fun;			//订阅者要触发的回调函数
    this._this =_this;		//订阅者订阅的对象
    this.key = key;			//订阅者订阅的key
    this.value = this.get();  // 将自己添加到订阅器
}
 
Watcher.prototype = {
    
    
    update: function() {
    
    
        this.run();
    },
    run: function() {
    
    
        var value = this._this.data[this.key];
        var oldVal = this.value;
        if (value !== oldVal) {
    
    
            this.value = value;
            this.fun.call(this._this, value, oldVal);
        }
    },
    get: function() {
    
    
        Dep.self = this;  
        var value = this._this.data[this.key]  
        Dep.self = null;  
        return value;
    }
};

3.オブザーバーとウォッチャーを接続します

function myVue (data, el, exp) {
    
    
    this.data = data;
    observe(data);
    el.innerHTML = this.data[exp];
    new Watcher(this, exp, function (value) {
    
    
        el.innerHTML = value;
    });
    return this;
}

4.ビューレイヤーに連絡します

<body>
    <h1 id="text">{
   
   {text}}</h1>
</body>
<script type="text/javascript">
    var ele = document.querySelector('#text');
    var myVue = new myVue({
     
     
        name: 'hello world'
    }, ele, 'text');
 
</script>

補足
ここに写真の説明を挿入
WeChatで[Webギャラリー]を検索し、フルスタックのブログプロジェクト返信してプロジェクトのソースコードとフォローアップの実用的な記事のチュートリアルを入手してください毎日最もシンプルでシンプルな言語を使用して、基本的なコンピューターの知識とフロントエンドテクノロジーを微妙に向上させます。専任のウェブフルスタックエンジニアであるXiaomiCongee、またお会いしましょう!

ここに写真の説明を挿入
ノードの背景

おすすめ

転載: blog.csdn.net/gitchatxiaomi/article/details/108808083