範圍樹

當我們需要將單個 html 元素繫結到單個變數時,前面的示例就足夠了。

實際上 - 我們需要將許多元素繫結到許多變數:

<span ng-repeat="number in [1,2,3,4,5]">{{number}}</span>

這個 ng-repeat 將 5 個元素繫結到 5 個名為 number 的變數,每個變數都有不同的值!

angular 實現此行為的方式是為每個需要單獨變數的元素使用單獨的上下文。此上下文稱為範圍。

每個範圍都包含屬性,這些屬性是繫結到 DOM 的變數,$digest$watch 函式是作為範圍的方法實現的。

DOM 是一棵樹,變數需要在樹的不同級別使用:

<div>
    <input ng-model="person.name" />
    <span ng-repeat="number in [1,2,3,4,5]">{{number}} {{person.name}}</span>
</div>

但正如我們所看到的,ng-repeat 中變數的上下文(或範圍)與其上方的上下文不同。要解決這個問題 - angular 將範圍實現為樹。

每個範圍都有一個子陣列,呼叫它的 $digest 方法將執行它的所有子項的 $digest 方法。

這樣 - 在更改輸入後 - 為 div 的範圍呼叫 $digest,然後為其 5 個子節點執行 $digest - 這將更新其內容。

範圍的簡單實現可能如下所示:

function $scope(){
    this.$children = [];
    this.$watches = [];
}

$scope.prototype.$digest = function(){
    this.$watches.forEach(function($w){
        var val = $w.val();
        if($w.prevVal !== val){
            $w.callback(val, $w.prevVal);
          $w.prevVal = val;
        }
    });
    this.$children.forEach(function(c){
        c.$digest();
    });
}

$scope.prototype.$watch = function(val, callback){
    this.$watches.push({val:val, callback:callback, prevVal: val() })
}

注意:這是一個示例,而不是實際的角度程式碼