検索
ホームページウェブフロントエンドjsチュートリアルangularjs でのダーティ チェックを理解する

angularjs でのダーティ チェックを理解する

関連する推奨事項: 「angularjs チュートリアル

angularjs は双方向バインディングを実装します。これは、vue のdefineProperty とは異なります。その原理は、以下は、ダーティ チェック メカニズムの概要です。

angular.js の概要

  • AngularJs は mvvm フレームワークであり、そのコンポーネントは vm コンポーネントであり、スコープはデータ コレクションです。 vm コンポーネントの
  • AngularJs はディレクティブを通じて vm の動作を宣言します。これはウォッチャーとして実装され、スコープのプロパティの変更をリッスンし、最新のプロパティで UI を更新します
  • AngularJs の双方向バインディング: 例: 1 つは $ にバインドされます。scope 属性値は HTML 構造にバインドされます。$scope 属性値が変更されると、インターフェイスも変更されます。もう 1 つは、ユーザーが HTML 構造に対して操作を実行するときです。インターフェイス (クリック、入力、選択など) を実行すると、$scope 属性が自動的にトリガーされます。ダーティ チェック
  • angular はデータの変更をまったくリッスンしませんが、適切なタイミング ($watch) で、$rootScope から始まるすべての $scope を走査し、

属性値が正しいかどうかを確認します。変更があった場合は、変数 Dirty を使用してそれを true として記録し、再度 ($digest) を走査し、

    というように、特定の走査が完了し、これらの $scope の属性値が変更されていない場合、トラバーサルは終了します。
  • ダーティ変数はレコードとして使用されるため、ダーティ チェック機構と呼ばれます。
  • 要するに: スコープが作成されると、angular はテンプレートを解析し、バインディング値とイベント呼び出しを見つけて、それらを $watch;
  • # でバインドします。 ##
    $scope.$watch(string|function, listener, objectEquality, prettyPrintExpression)
    // string: 验证值或者function执行后return的string
    // listener: 如果验证值不同,则执行该监听函数
    // objectEquality:执行深检查
バインディングが完了すると、これらのプロパティの変更が自動的に検出され、$watch が実行され、対応する情報が angular 内の $$watchers にバインドされます。キュー (配列)、$digest がトリガーされると、angular は配列

を走査し、ダーティ変数を使用して $$watchers

# に記録された $scope 属性に変更があるかどうかを記録します。
##次の処理:
  • dirty が true かどうかを判定し、false の場合、$digest 再帰は実行されません。 (dirty のデフォルトは true)
$$watchers をトラバースし、対応する属性値の古い値と新しい値を取り出し、objectEquality に従って古い値と新しい値を比較します。

  • 2 つの値が異なる場合は、実行を続行します。 2 つの値が同じ場合は、dirty を false に設定します。

  • すべてのウォッチャーをチェックした後、dirty がまだ true である場合は、dirty を true に設定し、古い値を新しい値に置き換えます。

  • Inこのようにして、次の再帰ラウンドでは、古い値がこのラウンドの新しい値となり、$digest を再度呼び出します (簡単に言えば、2 回の再帰走査を実行して、古い値と新しい値の変化を確認することです)

  • 変更された値 $scope がインターフェイスに再レンダリングされます

  • $apply が $digest をトリガーします

  • 通常、$digest $apply を呼び出すと、内部で $digest 再帰トラバーサルがトリガーされます。
  • angular の内部命令は、ng-click などの $apply をカプセル化するため、通常は apply を手動で呼び出す必要はありません

apply の手動呼び出しが必要になる場合があります。手動トリガー

function($timeout) {
  // 当我们通过on('click')的方式触发某些更新的时候,可以这样做
  $timeout(() => { // 内置语法糖 $http, $timeout已经包含了apply
    $scope.name = 'lily'
  })
  // 也可以这样做
  $element.on('click', () => {
    $scope.name = 'david'
    $scope.$apply()
  })
}
    注: 再帰プロセス中は、次のように $apply を手動で呼び出してはいけません。 $watch のコールバック関数などの ng-click 関数。
  • 最後に、単純なダーティ チェック メカニズムを実装します
  • <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>angularjs脏检查实现</title>
    </head>
    <style type="text/css">
      button {
        height: 60px;
        width: 100px;
      }
    
      p {
        margin-left: 20px;
      }
    </style>
    
    <body>
      <div>
        <button type="button" ng-click="increase">增加</button>
        <button type="button" ng-click="decrease">减少</button>
        数量:<span ng-bind="data">0</span>
      </div>
      <br>
    </body>
    <script>
      window.onload = function () {
        /**
         * 声明构造函数
         */
        function Scope() {
          this.$$watchList = []; // angular内部会声明一个数组(包含监听的对象),在digest执行时去遍历
        }
    
        /**
         * 属性赋值给$scope
         * 类似angular解析controller的模板,把模板中的属性解析出来,属性赋值给$scope
         */
        Scope.prototype.getNewValue = function () {
          return $scope[this.name];
        }
    
        /**
         * 实现监听
         */
        Scope.prototype.$watch = function (name, listener) {
          let watch = {
            name: name,
            getNewValue: this.getNewValue,
            listener: listener || function () { }
          };
          // 当作用域创建时,angular会去解析模板,$watch用来绑定监听值和监听函数
          this.$$watchList.push(watch);
        }
    
        /**
        * 检查dirty,循环更新scope上的最新值
        */
        Scope.prototype.$digest = function () {
          console.log(&#39;$digest&#39;);
          let dirty = true; // 默认dirty变量为true
          let checkTimes = 0;
          while (dirty) {
            dirty = this.$valScope();
            checkTimes++;
            if (checkTimes > 10 && dirty) {
              throw new Error("循环过多");
            }
          }
        }
    
        /**
         * 验证值是否有变化
         */
        Scope.prototype.$valScope = function () {
          let dirty;
          let list = this.$$watchList;
          for (let i = 0; i < list.length; i++) {
            let watch = list[i];
            let newValue = watch.getNewValue();
            let oldValue = watch.last || undefined;
            if (newValue !== oldValue) {
              watch.listener(newValue, oldValue);
              dirty = true; // 如果新旧值不同,则继续遍历
            } else {
              dirty = false;
            }
            watch.last = newValue;
          }
          return dirty;
        }
    
        /**
         * 刷新scope
         */
        Scope.prototype.$apply = function (params) {
          let list = document.querySelectorAll(&#39;[ng-bind]&#39;);
          console.log(&#39;list&#39;, list)
          for (let i = 0, l = list.length; i < l; i++) {
            let bindData = list[i].getAttribute(&#39;ng-bind&#39;);
            console.log(&#39;bindData&#39;, bindData)
            console.log(&#39;list[i]&#39;, list[i])
            list[i].innerHTML = $scope[bindData];
          }
        }
    
        let $scope = new Scope(); // 实例化,声明$scope对象集合
        $scope.data = 0;
        $scope.increase = function () {
          this.data++;
        };
        $scope.decrease = function () {
          this.data--;
        };
    
        $scope.$watch(&#39;data&#39;, function(newValue, oldValue) { // 监听
            console.log("new: " + newValue + "=========" + "old: " + oldValue);
        });
    
    
        // 手动为button按钮添加onclick事件,并为通过闭包为其绑定了全局scope对象,绑定apply方法
        // 类似angular内部实现
        function startBind() {
          let list = document.querySelectorAll(&#39;[ng-click]&#39;);
          for (let i = 0, l = list.length; i < l; i++) {
            list[i].onclick = (function (index) {
              return function () {
                let func = this.getAttribute(&#39;ng-click&#39;);
                $scope[func]($scope);
                $scope.$digest();
                $scope.$apply()
              }
            })(i)
          }
        }
    
        // 初始化
        startBind();
      }
    
    </script>
    
    </html>
  • プログラミング関連の知識の詳細については、
プログラミング ビデオ

をご覧ください。 !

以上がangularjs でのダーティ チェックを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事は博客园で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
JavaScriptのデータ型:ブラウザとNodejsに違いはありますか?JavaScriptのデータ型:ブラウザとNodejsに違いはありますか?May 14, 2025 am 12:15 AM

JavaScriptコアデータ型は、ブラウザとnode.jsで一貫していますが、余分なタイプとは異なる方法で処理されます。 1)グローバルオブジェクトはブラウザのウィンドウであり、node.jsのグローバルです2)バイナリデータの処理に使用されるNode.jsの一意のバッファオブジェクト。 3)パフォーマンスと時間の処理にも違いがあり、環境に従ってコードを調整する必要があります。

JavaScriptコメント://および / * *を使用するためのガイドJavaScriptコメント://および / * *を使用するためのガイドMay 13, 2025 pm 03:49 PM

javascriptusestwotypesofcomments:シングルライン(//)およびマルチライン(//)

Python vs. JavaScript:開発者の比較分析Python vs. JavaScript:開発者の比較分析May 09, 2025 am 12:22 AM

PythonとJavaScriptの主な違いは、タイプシステムとアプリケーションシナリオです。 1。Pythonは、科学的コンピューティングとデータ分析に適した動的タイプを使用します。 2。JavaScriptは弱いタイプを採用し、フロントエンドとフルスタックの開発で広く使用されています。この2つは、非同期プログラミングとパフォーマンスの最適化に独自の利点があり、選択する際にプロジェクトの要件に従って決定する必要があります。

Python vs. JavaScript:ジョブに適したツールを選択するPython vs. JavaScript:ジョブに適したツールを選択するMay 08, 2025 am 12:10 AM

PythonまたはJavaScriptを選択するかどうかは、プロジェクトの種類によって異なります。1)データサイエンスおよび自動化タスクのPythonを選択します。 2)フロントエンドとフルスタック開発のためにJavaScriptを選択します。 Pythonは、データ処理と自動化における強力なライブラリに好まれていますが、JavaScriptはWebインタラクションとフルスタック開発の利点に不可欠です。

PythonとJavaScript:それぞれの強みを理解するPythonとJavaScript:それぞれの強みを理解するMay 06, 2025 am 12:15 AM

PythonとJavaScriptにはそれぞれ独自の利点があり、選択はプロジェクトのニーズと個人的な好みに依存します。 1. Pythonは、データサイエンスやバックエンド開発に適した簡潔な構文を備えた学習が簡単ですが、実行速度が遅くなっています。 2。JavaScriptはフロントエンド開発のいたるところにあり、強力な非同期プログラミング機能を備えています。 node.jsはフルスタックの開発に適していますが、構文は複雑でエラーが発生しやすい場合があります。

JavaScriptのコア:CまたはCの上に構築されていますか?JavaScriptのコア:CまたはCの上に構築されていますか?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc;それは、解釈されていることを解釈しました。

JavaScriptアプリケーション:フロントエンドからバックエンドまでJavaScriptアプリケーション:フロントエンドからバックエンドまでMay 04, 2025 am 12:12 AM

JavaScriptは、フロントエンドおよびバックエンド開発に使用できます。フロントエンドは、DOM操作を介してユーザーエクスペリエンスを強化し、バックエンドはnode.jsを介してサーバータスクを処理することを処理します。 1.フロントエンドの例:Webページテキストのコンテンツを変更します。 2。バックエンドの例:node.jsサーバーを作成します。

Python vs. Javascript:どの言語を学ぶべきですか?Python vs. Javascript:どの言語を学ぶべきですか?May 03, 2025 am 12:10 AM

PythonまたはJavaScriptの選択は、キャリア開発、学習曲線、エコシステムに基づいている必要があります。1)キャリア開発:Pythonはデータサイエンスとバックエンド開発に適していますが、JavaScriptはフロントエンドおよびフルスタック開発に適しています。 2)学習曲線:Python構文は簡潔で初心者に適しています。 JavaScriptの構文は柔軟です。 3)エコシステム:Pythonには豊富な科学コンピューティングライブラリがあり、JavaScriptには強力なフロントエンドフレームワークがあります。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール