angularjs 中的$digest和$apply區別


$digest和$apply

在Angular中,有$apply和$digest兩個函數,我們剛才是通過$digest來讓這個數據應用到界面上。但這個時候,也可以不用$digest,而是使用$apply,效果是一樣的,那么,它們的差異是什么呢?

最直接的差異是,$apply可以帶參數,它可以接受一個函數,然后在應用數據之后,調用這個函數。除此之外,還有別的區別嗎?

在簡單的數據模型中,這兩者沒有本質差別,但是當有層次結構的時候,就不一樣了。考慮到有兩層作用域,我們可以在父作用域上調用這兩個函數,也可以在子作用域上調用,這個時候就能看到差別了。

對於$digest來說,在父作用域和子作用域上調用是有差別的,但是,對於$apply來說,這兩者一樣。我們來構造一個特殊的示例:

var app = angular.module("test", []);

app.directive("increasea", function() {
    return function (scope, element, attr) {
        element.on("click", function() {
            scope.a++;
            scope.$digest();
        });
    };
});

app.directive("increaseb", function() {
    return function (scope, element, attr) {
        element.on("click", function() {
            scope.b++;
            scope.$digest();    //這個換成$apply即可
        });
    };
});

app.controller("OuterCtrl", ["$scope", function($scope) {
    $scope.a = 1;

    $scope.$watch("a", function(newVal) {
        console.log("a:" + newVal);
    });

    $scope.$on("test", function(evt) {
        $scope.a++;
    });
}]);

app.controller("InnerCtrl", ["$scope", function($scope) {
    $scope.b = 2;

    $scope.$watch("b", function(newVal) {
        console.log("b:" + newVal);
        $scope.$emit("test", newVal);
    });
}]);
<div ng-app="test">
    <div ng-controller="OuterCtrl">
        <div ng-controller="InnerCtrl">
            <button increaseb>increase b</button>
            <span ng-bind="b"></span>
        </div>
        <button increasea>increase a</button>
        <span ng-bind="a"></span>
    </div>
</div>

 

這時候,我們就能看出差別了,在increase b按鈕上點擊,這時候,a跟b的值其實都已經變化了,但是界面上的a沒有更新,直到點擊一次increase a,這時候剛才對a的累加才會一次更新上來。怎么解決這個問題呢?只需在increaseb這個指令的實現中,把$digest換成$apply即可。

當調用$digest的時候,只觸發當前作用域和它的子作用域上的監控,但是當調用$apply的時候,會觸發作用域樹上的所有監控。

因此,從性能上講,如果能確定自己作的這個數據變更所造成的影響范圍,應當盡量調用$digest,只有當無法精確知道數據變更造成的影響范圍時,才去用$apply,很暴力地遍歷整個作用域樹,調用其中所有的監控。

從另外一個角度,我們也可以看到,為什么調用外部框架的時候,是推薦放在$apply中,因為只有這個地方才是對所有數據變更都應用的地方,如果用$digest,有可能臨時丟失數據變更。

 

轉自: https://github.com/xufei/blog/issues/10


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM