1. オブジェクトの変更検出次に、データの変更を検出するロジックをシミュレートします。 ここで、これから行うことを強調しておきます。データの変更を外部に通知します (その後、外部はビューの再レンダリングなど、独自の論理処理を実行します)。 コーディングを始める前に、まず次の質問に答える必要があります。 1. オブジェクトの変化を検出するにはどうすればよいでしょうか?
2. データが変更された場合、誰に通知しますか?
3. 誰に頼ればいいのか?
4. いつ通知されますか?
5. 依存関係をいつ収集しますか?
6.データはどこで収集されますか?
コードは次のとおりです (直接実行できます)。 // 依存関係を保存するために使用されるグローバル変数 let globalData = undefined; // データをレスポンシブに変換する function defineReactive (obj, key, val) { // 依存関係リスト letdependList = [] Object.defineProperty(obj, キー, { 列挙可能: true、 設定可能: true、 取得: 関数 () { // 依存関係を収集する (ウォッチャー) グローバルデータ && 依存リスト.push(グローバルデータ) 戻り値 }, 設定: 関数 reactiveSetter (newVal) { if(val === newVal){ 戻る } // 通知の依存関係 (ウォッチャー) 依存リスト.forEach(w => { w.update(新しい値、val) }) val = 新しい値 } }); } // クラス Watcher に依存{ コンストラクタ(データ、キー、コールバック){ this.data = データ; this.key = キー; this.callback = コールバック; this.val = this.get(); } // このコードは依存関係リストに自身を追加できます get(){ // 依存関係を globalData に保存する グローバルデータ = これ; // データを読み取るときに依存関係を収集します let value = this.data[this.key] グローバルデータ = 未定義 戻り値; } // データが変更されたときに通知を受け取り、外部に通知します update(newVal, oldVal){ this.callback(新しいVal、古いVal) } } /* 以下はテストコードです */ データを {} とします。 // name 属性をレスポンシブにする defineReactive(data, 'age', '88') // データの経過時間が変わると、ウォッチャーに通知され、ウォッチャーは外部に通知します。new Watcher(data, 'age', (newVal, oldVal) => { console.log(`外の世界: newVal = ${newVal}; oldVal = ${oldVal}`) }) data.age -= 1 // コンソール出力: 外部: newVal = 87; oldVal = 88 コンソールで 添付されているのは、Data、defineReactive、dependList、Watcher と外部世界との関係図です。 まず、defineReactive() メソッド ( 外部はWatcher( データが変更されると ( 2. オブジェクトに関する質問考えてみてください。上記の例では、 しません。セッターがトリガーされないためです。以下をお読みください: <!DOCTYPE html> <html lang="ja"> <ヘッド> <メタ文字セット="UTF-8"> <meta name="viewport" content="width=デバイス幅、初期スケール=1.0"> <title>ドキュメント</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <本文> <div id='アプリ'> <セクション> {{ p1.name }} {{ p1.age }} </セクション> </div> <スクリプト> constアプリ = 新しいVue({ el: '#app', データ: { p1: { 名前: 'ph', 年齢: 18 } } }) </スクリプト> </本文> </html> 実行後、ページに この問題を解決するために、Vue は vm.$set と vm.$delete という 2 つの API (後で紹介します) を提供します。 注意: ここで 配列変更検出3.1 背景もし、 関数defineReactive(obj, key, val) { Object.defineProperty(obj, キー, { 列挙可能: true、 設定可能: true、 取得: 関数 () { console.log(`get val = ${val}`) 戻り値 }, 設定: 関数 reactiveSetter (newVal) { if(val === newVal){ 戻る } console.log(`set val = ${newVal}; oldVal = ${val}`) val = 新しい値 } }); } // 以下はテストコードです {1} データを {} とします defineReactive(データ, 'a', [11,22]) data.a.push(33) // get val = 11,22 (setterはトリガーされません) {2} data.a // 値 = 11,22,33 を取得 data.a = 1 // set val = 1; oldVal = 11,22,33 (トリガー セッター) push() メソッドを介して配列の値を変更しても、セッター (行 {2}) はトリガーされないため、外部に通知することはできません。これは問題を示しているようです。Object.definePropery() メソッドでは、オブジェクトのみをレスポンシブに変換できますが、配列はレスポンシブに変換できません。 実際、Object.definePropery() は配列をレスポンシブな配列に変換できます。例をご覧ください: // 上記の例を続けて、テスト コード (行 {1}) を次のように変更します。 データ = [] リアクティブを定義します(データ、'0'、11) data[0] = 22 // val = 22; oldVal = 11 に設定 data.push(33) // {10} はトリガーされません Object.definePropery() は配列をレスポンシブにすることができますが、 したがって、Vue では、データを応答性に変換するために 2 セットのメソッドが使用されます。オブジェクトは Object.defineProperty() を使用し、配列は別のセットを使用します。 3.2 実装es6 では、Proxy を使用して配列の変更を検出できます。例をご覧ください: データ = [11,22]とする p = new Proxy(data, { 設定: 関数(ターゲット、プロパティ、値、レシーバー) { ターゲット[prop] = 値; console.log('プロパティセット: ' + prop + ' = ' + 値); true を返します。 } }) コンソールログ(p) p.push(33) /* 出力: [ 11 、 22 ] プロパティセット: 2 = 33 プロパティセット: 長さ = 3 */ es6 より前は少し面倒でしたが、インターセプターを使うことができました。原則としては、 // 配列のプロトタイプ let arrayPrototype = Array.prototype // インターセプターを作成する let interceptor = Object.create(arrayPrototype) // インターセプターを元の配列のメソッドに関連付けます。('push,pop,unshift,shift,splice,sort,reverse').split(',') .forEach(メソッド => { origin = arrayPrototype[メソッド]とします。 Object.defineProperty(インターセプター、メソッド、{ 値: 関数(...引数){ console.log(`インターセプター: args = ${args}`) origin.apply(this, args); を返します。 }, 列挙可能: false、 書き込み可能: true、 設定可能: true }) }); // テスト let arr1 = ['a'] arr2 = [10]とする arr1.push('b') // 配列 arr2 の変更を検出する Object.setPrototypeOf(arr2, interceptor) // {20} arr2.push(11) // インターセプター: args = 11 arr2.unshift(22) // インターセプター: args = 22 この例では、配列自体の内容を変更できる 7 つのメソッドをインターセプターに追加します。配列の変更を検出する必要がある場合は、配列のプロトタイプをインターセプターにポイントします (行 {20})。 push などの 7 つのメソッドを通じて配列を変更すると、インターセプターでトリガーされ、外部に通知できるようになります。 この時点では、配列の変更を検出するタスクのみが完了しています。 データが変更されたら、外部に通知します。上記のエンコーディング実装はオブジェクト データ専用ですが、ここでは配列データ用に実装する必要があります。 同じ質問について考えてみましょう: 1. 配列の変更を検出するにはどうすればよいでしょうか?
2. データが変更された場合、誰に通知しますか?
3. 誰に頼ればいいのか?
4. いつ通知されますか?
5. 依存関係をいつ収集しますか?
6.データはどこで収集されますか?
以上です。ここでは詳細には触れません。次の記事では、Vue におけるデータ検出に関するソースコードを抽出し、この記事と合わせて簡単に分析してみたいと思います。 IV. 配列に関する質問// vue.js を自分でインポートする必要があります。今後はコアコードのみをリストするようにします <div id='app'> <セクション> {{p1[0]}} {{ p1[1] }} </セクション> </div> <スクリプト> constアプリ = 新しいVue({ el: '#app', データ: { p1: ['ph', '18'] } }) </スクリプト> 実行後、ページに 上記は、vue 検出データ変更の基本的な実装の簡単な分析です。vue 検出データ変更の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
<<: CentOS8 Linux 8.0.1905 のインストール手順(図解)
>>: MySQLのクラスタモードでのgalera-clusterのデプロイメントの詳細説明
目次VMware バープスイート1. 仮想マシンイメージとVMwareのインストールと使用2. 仮想...
実施効果: 1. count(1) と count(*)テーブル内のデータ量が多い場合、テーブルを分...
目次1. テレポート1.1 テレポートの紹介1.2 テレポートの使用1.3 プレビュー効果2. サス...
HTML 中心のフロントエンド開発は、ほぼ Web 標準の意味です。共通しているのは「分離」という考...
この記事では、シンプルなカレンダー効果を実現するためのjsの具体的なコードを参考までに共有します。具...
** CentOS7 で yum ソースをインストールし、rz および sz コマンドをアップロー...
要素の両端を揃える配置レイアウトは、実際の開発のいたるところで見られます。これは、フレックスレイアウ...
1. テーブルステートメントを作成します。 テーブル「従業員」を作成します( `emp_no` in...
準備: 1. VMwareワークステーションソフトウェアをインストールする2. Kali Linux...
Dockerfileを初期化するプロジェクトの名前が express であると仮定して、expres...
ファイルシステムとは何かInnoDB や MyIASM などのストレージ エンジンはテーブルをディス...
クリック後にポップアップボックスを実現し、上下左右に中央揃えし、灰色の透明マスクを追加してウィンドウ...
目次1. MySQLをダウンロードする2. 圧縮パッケージを解凍する3. MySQLを初期化する4....
この記事は主に、Nginx のフォワード プロキシとリバース プロキシ、および負荷分散機能の設定コー...
準備Windows Server 2008 R2 Enterprise (2.40GH、8GB、64...