前書き
Vue.js には 2 つのコア機能があることは誰もが知っています。1 つはレスポンシブ データ バインディング システム、もう 1 つはコンポーネント システムです。この記事では、ほぼすべての Vue の入門書で言及されている hello world 双方向バインディングの実装方法についてのみ説明します。最初に関連する知識ポイントについて説明し、次にソース コードを参照して、できるだけ少ないコードで Hello World の開始サンプルを実装しましょう。
1. アクセサー プロパティ
アクセサー プロパティはオブジェクト内で直接設定することはできませんが、defineProperty() メソッドを通じて個別に定義する必要があります。
var obj = { }; // 为obj定义一个名为hello的访问器属性 Object.defineProperty(obj, "hello", { get: function () {return sth}, set: function (val) {/* do sth */} })
obj.hello // アクセサー プロパティは通常のプロパティと同様に読み取ることができます
アクセサー プロパティの「値」は特別であり、アクセサー プロパティの値の読み取りまたは設定は、実際には内部機能である get 関数と set 関数を呼び出します。
obj.hello // 属性を読み取るには、get 関数を呼び出し、get 関数の戻り値を返します。
obj.hello = "abc" // 属性に値を代入する場合は、 set 関数を呼び出すには、代入は実際にはパラメータを渡します
get メソッドと set メソッド内のこれは両方とも obj を指します。つまり、get 関数と set 関数はオブジェクト内の値を操作できます。さらに、アクセサー属性は同じ名前の通常の属性を「上書き」します。これは、アクセサー属性が最初にアクセスされ、同じ名前の通常の属性は無視されるためです(つまり、いわゆる「ハイジャック」されます)。 )。
2. 最小限の双方向バインディングの実装
この例の効果は次のとおりです: テキスト ボックスに入力されたテキストが変更されると、同じテキスト コンテンツが js またはコンソールで同期して表示されます。 obj.name の値に応じてビューが更新されます。これにより、モデル => ビューとビュー => モデルの双方向バインディングが実現され、応答性が高くなります。
上記は、Vue が双方向バインディングを実装する基本原則です。
3. タスクを分解する
上記の例は、原理を説明するためのものです。
最終的に達成したいのは:
まずタスクをいくつかのサブタスクに分割します:
1. 入力ボックスとテキストノードを data 内のデータにバインドします
2. の内容を変更します入力ボックス データ内のデータが同期して変更されるとき。つまり、ビュー => モデルの変更です。
3. データ内のデータが変更されると、同時にテキストノードの内容も変更されます。つまり、モデル => ビューが変更されます。
タスク 1 を達成するには、DOM をコンパイルする必要があります。これは DocumentFragment です。
4. DocumentFragment
DocumentFragment (ドキュメントフラグメント) は、複数の子ノードを含めることができるので、その子ノードのみがターゲットノードに挿入されます。それはノードのセットのコンテナーとして機能します。 DocumentFragment を使用してノードを処理する速度とパフォーマンスは、DOM を直接操作するよりもはるかに優れています。 Vue はコンパイル時に、マウント ターゲットのすべての子ノードを DocumentFragment にハイジャック (実際にはハイジャック) し、いくつかの処理の後、DocumentFragment が全体として返され、マウント ターゲットに挿入されます。
5. データ初期化バインディング
上記のコードはタスク 1 を実装しています。入力ボックスとテキスト ノードに hello world がレンダリングされていることがわかります。
6. レスポンシブデータバインディング
タスク 2 の実装アイデアを見てみましょう: 入力ボックスにデータを入力するとき、最初に入力イベント (またはキーアップ、変更イベント) をトリガーし、次に対応するイベント プログラムでは、入力ボックスの値を取得し、それを vm インスタンスの text 属性に割り当てます。データ内のテキストを vm のアクセサー プロパティとしてハイジャックするには、defineProperty を使用します。そのため、vm.text に値を割り当てると、set メソッドがトリガーされます。
set メソッドで行うべき主な作業は 2 つあり、1 つ目は属性の値を更新することであり、2 つ目はタスク 3 に残ります。
タスク 2 が完了しました。テキスト属性の値は、入力ボックスの内容と同期して変更されます。
7. 購読/公開モード (購読&公開)
テキスト属性が変更されました。 set メソッドがトリガーされましたが、テキスト ノードの内容は変更されませんでした。テキストにバインドされているテキスト ノードも同期的に変更するにはどうすればよいですか?ここにはもう 1 つの知識ポイントがあります。それは、サブスクリプション出版モデルです。
サブスクリプション パブリッシュ パターン (オブザーバー パターンとも呼ばれる) は 1 対多の関係を定義し、トピック オブジェクトのステータスが変化したときに、複数のオブザーバーが特定のトピック オブジェクトを同時に監視できるようにします。通知されます。
パブリッシャーが通知を発行 => トピックオブジェクトが通知を受け取り、サブスクライバーにプッシュ => サブスクライバーが対応する操作を実行
前にも述べたように、set メソッドがトリガーされたときに 2 番目に行うことは次のとおりです。 as 発行者は、「私は属性テキストであり、変更されました」という通知を発行します。テキスト ノードはサブスクライバとして機能し、メッセージの受信後に対応する更新操作を実行します。
8. 双方向バインディングの実装
復習すると、新しい Vue が作成されるたびに、主に 2 つのことを実行します。1 つ目はデータを監視することです: observ(data)、2 つ目は HTML をコンパイルすることです: nodeToFragement (id) 。
データを監視するプロセスで、データ内の属性ごとにテーマ オブジェクト dep が生成されます。
HTML のコンパイルのプロセス中に、データ バインディングに関連するノードごとにサブスクライバー ウォッチャーが生成され、ウォッチャーは対応する属性の dep に自分自身を追加します。
入力ボックスの内容を変更 => イベント コールバック関数の属性値を変更 => 属性の set メソッドをトリガーするを実装しました。
次に実装する必要があるのは、通知の発行 dep.notify() => サブスクライバーの更新メソッドのトリガー => ビューの更新です。
ここでの重要なロジックは、関連付けられた属性の dep にウォッチャーを追加する方法です。
HTML のコンパイルのプロセス中に、データに関連付けられたノードごとにウォッチャーが生成されます。ウォッチャー機能では何が起こるのでしょうか?
まず、それ自体をグローバル変数 Dep.target に割り当てます。次に、update メソッドが実行され、次に get メソッドが実行され、vm のアクセサー属性が読み取られ、アクセスがトリガーされます。アクセサー属性の get メソッド。 get メソッドでは、対応するアクセサー属性の dep にウォッチャーが追加されます。
再度、属性の値を取得し、ビューを更新します。
最後に、Dep.target を空に設定します。これはグローバル変数であり、watcher と dep の間の唯一のブリッジであるため、Dep.target には常に 1 つの値のみが含まれるようにする必要があります。
この時点で、Hello World 双方向バインディングは基本的に実装されました。テキストの内容は入力ボックスの内容と同期して変更されます。コントローラーの vm.text の値を変更すると、テキストの内容も同期して反映されます。
概要
以上は vue.js の双方向バインディングの実装原理に関するものです。この記事の内容が皆さんの学習や仕事に役立つことを願っています。ご質問がある場合は、メッセージを残してください。 PHP 中国語 Web サイトのサポートをご利用いただきありがとうございます。
vue.js の双方向バインディングの実装原則と関連記事をさらに詳しく理解するには、PHP 中国語 Web サイトに注目してください。