Heim  >  Artikel  >  Web-Frontend  >  Dirty Checking in AngularJS verstehen

Dirty Checking in AngularJS verstehen

青灯夜游
青灯夜游nach vorne
2021-01-20 17:26:301953Durchsuche

Dirty Checking in AngularJS verstehen

Verwandte Empfehlungen: „AngularJS-Tutorial“

AngularJS implementiert die bidirektionale Bindung, die sich von vues defineProperty unterscheidet. Hier ist eine Zusammenfassung von

Angular.js-Einführung

    AngularJs ist ein MVVM-Framework und Scope ist eine Datensammlung von VM-Komponenten.
  • AngularJs verwendet Anweisungen, um das Verhalten von VM zu deklarieren den Bereich und die neuesten Eigenschaften aktualisieren. Die bidirektionale Bindung von UI
  • AngularJs: Zum Beispiel: Eine besteht darin, den Attributwert $scope an die HTML-Struktur zu binden. Die andere besteht darin, den Wert des $scope-Attributs an die HTML-Struktur zu binden. Die andere besteht darin, den Wert des $scope-Attributs an die Schnittstelle zu binden. Vorgänge wie Klicken, Tippen und Auswählen lösen automatisch Änderungen im $scope-Attribut aus Schnittstelle kann sich auch entsprechend ändern)
  • Änderungen von Bereichsattributen überwachen: Dirty Check
Dirty Check

    angular überwacht überhaupt keine Datenänderungen, durchläuft aber zum richtigen Zeitpunkt ($watch) alle $scopes beginnend mit $rootScope ,
  • Überprüfen Sie, ob sich die Attributwerte darauf geändert haben. Wenn es Änderungen gibt, verwenden Sie eine schmutzige Variable, um sie als wahr aufzuzeichnen, und wiederholen Sie den Vorgang. Traverse ($digest),
  • usw., bis a Wenn eine bestimmte Durchquerung abgeschlossen ist und sich die Attributwerte dieser $scopes nicht geändert haben, endet die Durchquerung.
  • Da eine Dirty-Variable als Datensatz verwendet wird, wird sie als Dirty-Checking-Mechanismus bezeichnet.
Kurz gesagt: Wenn der Bereich erstellt wird, analysiert Angular die Vorlage, ermittelt die Bindungswerte und Ereignisaufrufe und bindet sie mit $watch.

$scope.$watch(string|function, listener, objectEquality, prettyPrintExpression)
// string: 验证值或者function执行后return的string
// listener: 如果验证值不同,则执行该监听函数
// objectEquality:执行深检查
    Nach Abschluss der Bindung wird dies der Fall sein automatisch erkannt werden Wenn sich diese Attribute ändern, wird $watch ausgeführt und die entsprechenden Informationen werden an einen $$watchers innerhalb von Angular gebunden.
  • Es handelt sich um eine Warteschlange (Array), und wenn $digest ausgelöst wird, durchläuft Angular dieses Array.
  • und verwenden Sie eine Dirty-Variable, um aufzuzeichnen, ob sich die in $$watchers aufgezeichneten $scope-Attribute geändert haben.
Der nächste Prozess:

  • Beurteilen Sie, ob Dirty wahr ist, wird $digest nicht ausgeführt . Rekursion. (Dirty ist standardmäßig true)

  • Durchlaufen Sie $$watcher, nehmen Sie den alten Wert und den neuen Wert des entsprechenden Attributwerts heraus und vergleichen Sie den alten und neuen Wert gemäß objectEquality.

  • Wenn die beiden Werte unterschiedlich sind, fahren Sie mit der Ausführung fort. Wenn die beiden Werte gleich sind, setzen Sie dirty auf false.

  • Nachdem Sie alle Beobachter überprüft haben, stellen Sie Dirty auf „true“ ein und ersetzen Sie den alten Wert durch den neuen Wert.

  • Auf diese Weise wird in der nächsten Rekursionsrunde der alte Wert verwendet neuer Wert dieser Runde Rufen Sie $digest erneut auf (einfach ausgedrückt führt es zwei rekursive Durchläufe durch, um die Änderungen in den alten und neuen Werten zu überprüfen)

  • Den geänderten $scope erneut in die Schnittstelle rendern

$Apply-Trigger $digest

    Im Allgemeinen wird $digest nicht aufgerufen, um $apply aufzurufen, was intern die rekursive Durchquerung von $digest auslöst. Die internen Anweisungen von Angular kapseln $apply, z. B. ng-click, sodass im Allgemeinen kein manueller Vorgang erforderlich ist call apply
  • Apply manuell aufrufen

Manchmal muss es manuell ausgelöst werden

    function($timeout) {
      // 当我们通过on('click')的方式触发某些更新的时候,可以这样做
      $timeout(() => { // 内置语法糖 $http, $timeout已经包含了apply
        $scope.name = 'lily'
      })
      // 也可以这样做
      $element.on('click', () => {
        $scope.name = 'david'
        $scope.$apply()
      })
    }
  • Hinweis: Während des rekursiven Prozesses darf $apply nicht manuell aufgerufen werden, z. B. in der ng-click-Funktion, z. B. in der Callback-Funktion von $watch.
Implementieren Sie abschließend einen einfachen Dirty-Check-Mechanismus
<!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>
Weitere Programmierkenntnisse finden Sie unter:

Programmiervideo

! !

Das obige ist der detaillierte Inhalt vonDirty Checking in AngularJS verstehen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen