ホームページ  >  記事  >  ウェブフロントエンド  >  angular1 の学習ノート。angularjs でのビュー モデルの同期プロセスが含まれています。

angular1 の学習ノート。angularjs でのビュー モデルの同期プロセスが含まれています。

寻∝梦
寻∝梦オリジナル
2018-09-07 17:28:251345ブラウズ

これはangularjsの個人的な理解メモです。ここで、皆さんに見てもらえるように書いてみましょう

事の発端は、プロジェクトAでの出会いです。小さな問題: このプロジェクトには販売数量を入力するための入力ボックスが必要ですが、ユーザーが入力した後、入力データに基づいて手数料が計算されます。当然ng-modelとng-changeを使用しましたが、概ね問題ありません。問題は、入力ボックスの下にすべて売却するボタンがあることです。このボタンをクリックすると、売却額が自動的に設定されます。しかし実際には、この時点ではプログラムは手数料を計算しません。
トラブルシューティングを行ってドキュメントを調べた結果、ng-change に問題があることがわかりました。 ng-change プロンプトに関する Angular の公式ドキュメント:
値の変更がモデルから来る場合、式は評価されません:
ng-change のソース コードも非常に単純です:

  var ngChangeDirective = valueFn({
      restrict: 'A',
      require: 'ngModel',
      link: function(scope, element, attr, ctrl) {
        ctrl.$viewChangeListeners.push(function() {
          scope.$eval(attr.ngChange);
        });
      }
    });

そこから ng-change も確認できます。ビューからモデルまでの監視のみが行われます。そのため、js で ng-model の変数を直接変更しても、ng-change はトリガーされません。
問題が見つかったので、解決策は難しくありません。ng-change を放棄して、代わりに $watch を使用してください。
でも、もう終わりですか?ビューの変更からモデルの同期更新まで、変数は正確に何を経るのでしょうか?逆も同じですか?
そこで、ng-model のソースコードをもう一度見てみたところ、何も見つかりませんでしたが、予想外に次のことを学びました。
ng-change はモデルの値が変更される前に実行されるということです。 ng-model のソース コードにはそのような関数があります:

function setupModelWatcher(ctrl) {
  // model -> value
  // !!!Note: we cannot use a normal scope.$watch as we want to detect the following:
  // !!!1. scope value is 'a'
  // !!! 2. user enters 'b'
  // !!!3. ng-change kicks in and reverts scope value to 'a'
  //    -> scope value did not change since the last digest as
  //       ng-change executes in apply phase
  // !!!4. view should be changed back to 'a'
  ctrl.$$scope.$watch(function ngModelWatch(scope) {
    var modelValue = ctrl.$$ngModelGet(scope);

    // if scope model value and ngModel value are out of sync
    // This cannot be moved to the action function, because it would not catch the
    // case where the model is changed in the ngChange function or the model setter
    if (modelValue !== ctrl.$modelValue &&
      // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
      // eslint-disable-next-line no-self-compare
      (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
    ) {
      ctrl.$$setModelValue(modelValue);
    }

    return modelValue;
  });
}

中のコメントは、なぜ ng-change の後に変数モデルの値を変更する必要があるのか​​を説明しています。ng-change は変数の値を元に戻す可能性が高いため、変数がvalue 実際、それは変わっていません (API を作成するときは、あらゆる状況を考慮する必要があります!!)。この質問と以前の質問に関して、デモ コードは次のとおりです: http://php.cn/course/47.html

ソース コードを見ても何も得られないので、オンラインで記事を検索してください。このプロセス中に良い記事を見つけました。この記事では

$formatters$parsers$render、および $setViewValue。もうここでは紹介しません。学習する必要がある場合は、原文はここにあります: http://php.cn/course/47.html<code>$formatters,$parsers,$render以及$setViewValue。这里就不再介绍了,如果需要学习,原文在这里:http://php.cn/course/47.html

在学习$setViewValue时也发现一个很容易被坑的点:在调用$setViewValue时,如果参数是引用变量,那么如果引用变量地址没变,则这个变量被认为没有改变,如 var map = [‘er’, ’tr’];那么map.pop();之后$setViewValue并不认为map值改变了。关于这个具体可以看我对这个问题的回答。(想看更多就到PHP中文网AngularJS开发手册中学习)

ng-model也有这个问题,这个在ng-model源码注释中可以看到:

However, custom controls might also pass objects to this method. In
this case, we should make a copy of the object before passing it to
$setViewValue. This is because ngModel does not perform a deep
watch of objects, it only looks for a change of identity.

If you only change the property of the object then ngModel will not
realize that the object has changed and will not invoke the $parsers
and $validators pipelines.

从上面也可以看到其实一个变量的更新由view到model和model到view不止$formatters$parsers管道,那么还有哪些呢?

在查了一圈资料后找到一个很清晰的解释:https://stackoverflow.com/que...,大家其实只需要看问题的回答,问题实在太长了。。。
这个回答中有个demo链接,我copy了一下并做了写小修改放在这个地址了:http://php.cn/course/47.html,这个demo很清晰的显示了变量更新的过程,细节就不再累述了,这里只把结果总结如下:
从model到view:
model值修改 ----> $formatters管道 ----> $render函数 ----> $validators ----> $watch函数

从view到model:
view值修改 ----> $setViewValue函数----> $parsers管道 ----> $validators ----> $viewChangeListener函数 ----> $watch函数
我们也可以直接调用$setViewValue函数去直接改变$viewValue 的值,流程会和上面一样。
注意在使用$setViewValue时一定要警惕参数是引用变量的情况,这个坑在上文也已经提到了。

本文没有具体介绍$formatters$parsers

私が $setViewValue を学習していたとき、ポイント: $setViewValue を呼び出すとき、パラメータが参照変数の場合、参照変数のアドレスが変更されていない場合、その変数は変更されていないと見なされます。 as var map = ['er', 'tr'] ;$setViewValue は、map.pop() の後にマップ値が変更されたとはみなしません。詳細については、この質問に対する私の回答を参照してください。 (さらに詳しく知りたい場合は、PHP 中国語 Web サイトAngularJS 開発マニュアル🎜 にアクセスして学習してください)🎜🎜ng-モデルにもこの問題があり、これは ng-model のソース コードのコメントで確認できます: 🎜🎜
ただし、カスタム コントロールもこのメソッドにオブジェクトを渡す可能性があります。この場合、前にオブジェクトのコピーを作成する必要があります。それを🎜$setViewValueに渡します。これは、ngModel がオブジェクトの詳細な監視を実行せず、アイデンティティの変更のみを検索するためです。オブジェクトのプロパティを使用すると、ngModel はオブジェクトが変更されたことを認識せず、$parsers🎜 および $validators パイプラインを呼び出しません。🎜
🎜また、上記のことから、ビューからモデルへ、モデルからビューへ変数を更新するためのパイプラインは、実際には $formatters$parsers だけではありません。他に何があるのか​​もわかります。 ? 🎜🎜多くの情報をチェックした結果、非常に明確な説明を見つけました: https://stackoverflow.com/que... 実際、質問に対する答えを読むだけで十分です。質問は長すぎます。 。 。 🎜この回答にはデモリンクがあり、それをコピーして少し変更し、次のアドレスに置きました: http://php.cn/course/47.html このデモは変数更新のプロセスを明確に示しています。詳細は繰り返しませんが、ここでは次のように結果を要約するだけです。 🎜モデルからビューへ: 🎜モデル値の変更----> $formattersPipeline----> $render 関数 ----> $validators ----> $watch 関数 🎜🎜ビューからモデルへ: 🎜ビューの値の変更 - ---> $setViewValue関数---> $parsersパイプライン---> $validators --- - > $viewChangeListener 関数 ----> $watch 関数🎜 $setViewValue 関数を直接呼び出して、 を直接変更することもできます。 >$viewValueの値、処理は上記と同じになります。 🎜 $setViewValue を使用する場合は、変数を参照するパラメーターに注意する必要があることに注意してください。この落とし穴についても上で説明しました。 🎜🎜この記事では、$formatters パイプラインと $parsers パイプラインについては特に紹介しません。この部分については、記事内にあるリンクを参照してください。

この記事はここで終わります (さらに詳しく知りたい場合は、PHP 中国語 Web サイト AngularJS ユーザー マニュアル にアクセスして学習してください)。ご質問がある場合は、以下にメッセージを残してください。

以上がangular1 の学習ノート。angularjs でのビュー モデルの同期プロセスが含まれています。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。