この記事では、Vue 3.0 レスポンシブの使い方を説明します。

この記事では、Vue 3.0 レスポンシブの使い方を説明します。

Vue 2.0 Ojbect.definePropertyを使用してオブジェクトの既存のプロパティ値の読み取りと変更をハイジャックすることがわかっていますが、このAPIオブジェクトのプロパティの追加と削除を監視できません。また、オブジェクトの内部プロパティを深くハイジャックするには、初期化中に内部プロパティに対してOjbect.defineProperty再帰的に呼び出す必要があり、パフォーマンスの消費を引き起こします。これらの問題を解決するために、 Vue 3.0ではProxyを使用してレスポンシブ ロジックを書き直し、関連するパフォーマンスを最適化しました。

ユースケース

Vue 3.0でレスポンシブ API を書く方法の例を見てみましょう。

場合

changePerson 、レスポンシブ データpersonの値を変更できます。 person値の変更により、コンポーネントの再レンダリングがトリガーされ、 DOMが更新されます。

ここで、 Vue 3.0の使用において、開発者はreactive関数を使用してどのデータがレスポンシブ データであるかを判断し、不要なレスポンシブ パフォーマンスの消費を回避していることがわかります。たとえば、この場合、 nowIndexレスポンシブ データにする必要はありません。 (もちろん、 Vue 2.0 data関数の外で非レスポンシブなデータを定義することもできます)

次に、 reactive関数の実装原理を見てみましょう。

リアクティブAPI関連プロセス

反応的な

反応的な

コードの説明:

  • 1. ターゲットオブジェクトが読み取り専用targetの場合、読み取り専用オブジェクトは応答オブジェクトとして設定できないため、ターゲットオブジェクトを直接返します。
  • 2. createReactiveObject関数を呼び出してプロセスを続行します。

createReactiveObjectはレスポンシブオブジェクトを作成します

アクティブオブジェクトを作成する

コードの説明:

  • 1. 対象オブジェクトがデータまたはオブジェクトでない場合は、オブジェクトが直接返され、開発環境でエラー警告プロンプトが表示されます。
  • 2. targetがすでにProxyオブジェクトである場合、 target, (target['__v_raw']は非常に巧妙に設計されています。 targetProxyオブジェクトである場合、 target['__v_raw']getメソッドをトリガーし、キャッシュ オブジェクトreactiveMap検索して、 targetオブジェクトのProxyオブジェクトがtarget自体と等しいかどうかを確認します)。ここで例外が処理されます。レスポンシブ オブジェクトでreadonly関数が実行された場合は、続行する必要があります。
  • 3. reactiveMap内に対応するProxyオブジェクトがあるかどうかを確認し、対応するProxyオブジェクトを直接返します。
  • 4. 特定のデータのみがレスポンシブになるようにし、そうでない場合はtargetを返すだけにします。レスポンシブホワイトリストは次のようになります。

1. targetmarkRawメソッドによってマークされていないか、 targetオブジェクトに__v_skip属性値がないか、 __v_skip属性の値がfalseです。

2. target拡張不可能なオブジェクトであってはなりません。つまり、 target preventExtensionssealおよびfreezeメソッドを使用して実行されていません。

3. targetObjectまたはArrayです。

4. targetMapSetWeakMapWeakSetです。

  • 5. Proxy機能を使用してtargetオブジェクトをハイジャックすると、返される結果は応答オブジェクトになります。ここでの処理関数は、 targetオブジェクトによって異なります (両方の関数がパラメーターとして渡されます)。

1. ObjectまたはArrayの処理関数はcollectionHandlersです。

2. MapSetWeakMapWeakSetの処理関数はbaseHandlersです。

  • 6. レスポンシブ オブジェクトをキャッシュのreactiveMapに保存します。 keytargetvalueproxyです。

mutableHandlers 処理関数

可変ハンドラ

オブジェクトのプロパティにアクセスするとget関数がトリガーされ、オブジェクトのプロパティを設定するとset関数がトリガーされ、オブジェクトのプロパティを削除するとdeleteProperty関数がトリガーされ、 in has関数がトリガーされ、 getOwnPropertyNamesによってownKeys関数がトリガーされることがわかっています。次に、これらの関数のコード ロジックを見てみましょう。

関数を取得する

パラメータが渡されないため、デフォルトではisReadonlyshallow両方とも false になります。

得る

コードロジック:

  • 1. __v_isReactive属性が取得され、true が返された場合、ターゲットがすでにレスポンシブなオブジェクトであることを意味します。
  • 2. __v_isReadonly属性を取得し、false を返します。(readonly は別のレスポンシブ API ですが、ここでは説明しません)
  • 3. __v_raw属性を取得し、ターゲット自体を返します。この属性は、ターゲットがすでにレスポンシブなオブジェクトであるかどうかを判断するために使用されます。
  • 4. ターゲットが配列であり、includes、indexOf、lastIndexOfなどの属性にヒットした場合、配列のこれらの関数メソッドが実行され、配列の各要素に対してコレクション依存関係トラック( arrTrackOpTypes.GETi + '')が実行され、Reflectを通じて配列関数の値が取得されます。
  • 5.評価を反映する。
  • 6. それが特別な属性値であるかどうかを判断します: symbol__proto____v_isRef__isVu e。以前に取得した res に直接返される場合、後続の処理は実行されません。
  • 7.コレクションの依存関係を実行します。
  • 8. ref の場合、target が配列でないか、key が整数でない場合は、データの展開が実行されます。これには別のレスポンシブ API ref が関係しますが、ここでは説明しません。
  • 9. res がオブジェクトの場合、 reactive を再帰的に実行して、 res をレスポンシブ オブジェクトに変換します。ここで、ちょっとした最適化のヒントを紹介します。プロパティ値はアクセスされた後にのみハイジャックされるため、初期化中に完全にハイジャックされることによるパフォーマンスの消費を回避できます。

get関数を呼び出すタイミング

この質問に答える前に、セットアップに関する前回の記事「 Vue3.0 セットアップ機能の謎を解明」に戻る必要があります。

  • setup() 関数はsetupStatefulComponent関数内で実行され、実行結果が得られます。

セットアップステートフルコンポーネント

  • handleSetupResultのロジックは、間隔setupResultinstance.setupStateに割り当てることです。

ハンドルセットアップ結果

  • このinstance.setupStateinstance.ctxによってプロキシされるため、 instance.ctxにアクセスして変更すると、 instance.setupStateに直接アクセスして変更できます。

ctx

  • サブツリーVNodeレンダリングするには、 render関数を呼び出す必要があると前に説明しました。テンプレート コンパイルを使用して、例のrender関数がどのようになっているかを確認してみましょう。

与える

  • 非常に明確です。テンプレートをレンダリングするときに、 person属性オブジェクトはctxから取得されますが、これは実際にはsetupStateperson属性オブジェクトです。 setupStateperson属性オブジェクトのnameageaddressが取得されると、対応する値を取得するためにget関数が呼び出されます。

概要: コンポーネント インスタンス オブジェクトがレンダリング関数を実行してサブツリー VNode を生成すると、レスポンシブ オブジェクトの get 関数が呼び出されます。

トラックは依存関係を収集します

上記のget関数のコード説明でコレクション依存性について2 回言及しましたが、コレクション依存性とは何でしょうか?
応答性を実現するために、データが変更されたときに特定の関数を実行するなど、一部の機能が自動的に実装されます。副作用レンダリング関数はコンポーネントの再レンダリングをトリガーして DOM を更新できるため、ここで収集される依存関係は、データが変更されたときに実行する必要がある副作用レンダリング関数です。

つまり、 get関数が実行されると、対応するコンポーネントの副作用レンダリング関数が収集されます。

追跡

トラクト効果

最終結果を説明するために、次の例を挙げます。

結果

関数の設定

セット

コードロジック:

  • 1. 値が変更されていない場合は直接戻ります。
  • 2. Reflectを通じて新しい値を設定します。
  • 3. プロトタイプ チェーン上のプロパティではなく、新しいプロパティの場合はadd type triggerを実行し、変更されたプロパティの場合はset type triggerを実行します。 (Reflect.set がプロトタイプ チェーン上のプロパティである場合、セッターが再度呼び出されるため、トリガーを 2 回実行する必要はありません)。

トリガー分布の依存関係

トリガー

triggerコードのロジックは非常に明確です。get 関数によって収集された依存関係の targetMap から対応する関数を見つけ、これらの副作用レンダリング関数を実行して DOM を更新します。

取得と副作用レンダリング関数の関連付け

戻って別の質問に答えましょう。get 関数から収集された副作用レンダリング関数はどのように決定されるのでしょうか。つまり、person.name にアクセスするときに関連付ける副作用レンダリング関数をどのように決定するのでしょうか。

ロジックを段階的に整理してみましょう。

  • mountComponentをマウントする最後のステップは、副作用のあるレンダリング関数を実行することです。

マウントコンポーネント

  • setupRenderEffect 、最初にcomponentUpdateFnコンポーネント レンダリング関数を定義し、次にこのomponentUpdateFnReactiveEffectにカプセル化し、 ReactiveEffectオブジェクトのrunメソッドをコンポーネント オブジェクトのupdateプロパティに割り当て、次にupdateメソッドを実行します。このメソッドは、実際にはReactiveEffectオブジェクトのrunメソッドを実行します。

セットアップレンダリングエフェクト

  • ReactiveEffectの run メソッドは渡された関数を保持し、現在のシーンはcomponentUpdateFnコンポーネント レンダリング関数であり、2 つのグローバル変数effectStackactiveEffect使用します。
  • run メソッドを実行すると、まずcomponentUpdateFnactiveEffectに割り当てられ、 effectStackスタックにプッシュされ、次にcomponentUpdateFnメソッドが実行されます。実行が完了すると、 componentUpdateFnがスタックからポップされ、 activeEffectがスタックの先頭に新しい関数として割り当てられます。

リアクティブエフェクト

  • componentUpdateFnが実行されると、 renderComponentRootが呼び出され、基本的にコンポーネント インスタンス オブジェクトの render メソッドが実行されます。

コンポーネント更新関数

  • ここまででこの記事の内容です。renderメソッドで対応するデータにアクセスすると、get関数が呼び出されます。getで収集されるデータは

トラクト効果

ここでのスタック構造は、主にネストされた効果の問題を解決するために設計されています。

副作用レンダリング関数の実行フィルタリング

よく考えてみると疑問が湧いてくるのではないでしょうか?名前、年齢、住所はすべて変更されており、すべて同じレンダリング関数に関連付けられています。理論上、これら 3 つの値を同時に変更すると、3 つのコンポーネントの再レンダリングがトリガーされますが、これは明らかに不合理です。では、Vue はどのようにして実行を 1 回だけ制御するのでしょうか?

  • ReactiveEffect componentUpdateFnレンダリング関数をカプセル化するところに戻る必要があります。2 番目のパラメータ、 schedulerを見てみましょう。

リアクティブエフェクト

  • 依存関係をディスパッチするときに、 schedulerがある場合は、 schedulerが実行されます。

ここに画像の説明を挿入

  • queueJobの実行ロジックは、タスクがキュー内にある場合はそれをフィルタリングして実行しないことです。

キュージョブ

結論

この記事では、Vue3.0のレスポンシブ原則について詳しく紹介します。Proxyを使用してオブジェクトをハイジャックすると、オブジェクトにアクセスするときにgetメソッドがトリガーされ、このときに依存関係が収集されます。オブジェクトデータが変更されると、setメソッドがトリガーされ、依存関係がディスパッチされます。つまり、コンポーネントの副作用レンダリング関数が呼び出されます(これに限定されません)。これにより、コンポーネントが再レンダリングされ、DOMが更新されます。

これで、vue3.0 の応答性に関するこの記事は終了です。vue3.0 の応答性に関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • 夕食後にVue3.0のレスポンシブデータについてお話しましょう
  • Vue3.0 レスポンシブ システムのソース コードの行ごとの分析
  • Vue3.0データ応答原則の詳細な説明
  • Vue3.0 でレスポンシブデータを実装する方法をご存知ですか?
  • Vue3.0 レスポンシブ機能の原理の詳細

<<:  MySQLビューの原理と使用法の詳細な説明

>>:  MySQL インデックスの原理と使用例の分析

推薦する

HTML の marquee 属性の詳細な説明

このタグはHTML3.2の一部ではなく、MSIE3以降のカーネルでのみサポートされているため、IEカ...

H5 WeChatパブリックアカウント認証を実装するための簡単な手順

序文昨日、h5 WeChat認証の実装が必要なプロジェクトがありました。したがって、この機能を完了す...

Dockerはブリッジを追加し、IPアドレスの範囲を設定します

バイナリ docker 19.03 バージョンがインストール後に docker0 ブリッジを自動的に...

関数の分類の詳細な説明とJavascriptでのこのポイントの例

JS で関数を定義する 3 つの方法例を挙げて説明しましょう。 <スクリプト> //メソ...

Linux で開いているポートへのリモート アクセスを許可する方法

1. ファイアウォール設定ファイルを変更する # vi /etc/sysconfig/iptable...

Ubuntuサーバーの一般的なコマンドの概要

以下のコマンドのほとんどは、コンソール/ターミナル/シェルで入力する必要があります。 'su...

Raspberry PiにDockerをインストールする方法

Raspberry Pi は ARM アーキテクチャをベースとしているため、Docker のインスト...

MySQLのROUND関数の丸め演算における落とし穴の分析

この記事では、MySQL の ROUND 関数を使用した丸め操作の落とし穴を例を使って説明します。ご...

CSSマスクのフルスクリーン中央揃えを実装する方法

具体的なコードは次のとおりです。 <スタイル> #トーストローダーフルスクリーン{ 高さ...

keepalived+nginx の高可用性を実装する方法の例

1. keepalived の紹介Keepalived は、もともと LVS クラスタ システム内の...

MySQLの場合の使用例分析

まず、データベース テーブルを作成します。 テーブル `t_demo` を作成します ( `id` ...

MySQL 8.0 アトミック DDL 構文の詳細な説明

目次01 アトミックDDLの紹介02 一部のDDL操作の実行動作の変更03 DDL 操作のログを表示...

Angularコンポーネントのライフサイクルの詳しい説明(パート2)

目次1. ビューフック1. ngAfterViewInit および ngAfterViewCheck...

JSでHTML本文のスタイルを変更する

目次1. 本来の定義2. JS操作、幅の変更を例に3. 効果: 幅が変更されました 1. 本来の定義...

Linuxの一般的なコマンドでLinuxのmoreコマンドを使用する方法

more は、最もよく使用されるツールの 1 つです。最も一般的な使用方法は、出力コンテンツを表示し...