AngularJS Foundations

$digest vs $apply (略)

scope.$digest() will only fire watchers on current scope, scope.$apply will evaluate passed function and run $rootScope.$digest().

First one is faster, as needs to evaluate watchers for current scope, second one is slower (needs to evaluate watchers for$rootScope and all it's child scopes).

When error occurs in one of the watchers and you use scope.$digest, it's not handled via $exceptionHandler service, so you need to handle exception yourself. scope.$apply uses try catch block internally and passes all exceptions to $exceptionHandler.

/*index.html*/
<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css"/>

  <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.7.0/moment.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/tinycolor/0.11.1/tinycolor.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.12.1/TweenMax.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.18/angular.js"></script>
  <script src="app.js"></script>

  <style>
    .well{
      border: 30px solid black;
    }
  </style>
</head>
<body ng-app="demo" class="container">

<div class="well" ng-controller="OuterCtrl as outer">
<h2>Outer {{ time | heavy}}</h2>

  <div class="well" ng-controller="MiddleCtrl as middle">
  <h2>Middle {{ time }}</h2>


    <div class="well" ng-controller="InnerCtrl as inner">
    <h2>Inner {{ time }}</h2>

      <digest-button></digest-button>
      <apply-button></apply-button>

    </div>

  </div>

</div>


</body>
</html>

angular.module("demo", [])
    .filter("heavy", function () {
        return function (val) {
            return val + "      heavy!!! " + moment().format('SSS');
        }
    })


    .controller("OuterCtrl", function ($scope, $element) {
        var outer = this;

        $scope.$watch(function () {
            TweenMax.to($element, .5, {borderColor: tinycolor.fromRatio({
                r: Math.random(),
                g: Math.random(),
                b: Math.random()
            }).toHexString()})

        })
    })
    .controller("MiddleCtrl", function ($scope, $element) {
        var middle = this;

        $scope.$watch(function () {
            TweenMax.to($element, .5, {borderColor: tinycolor.fromRatio({
                r: Math.random(),
                g: Math.random(),
                b: Math.random()
            }).toHexString()})

        })
    })
    .controller("InnerCtrl", function ($scope, $element) {
        var inner = this;

        $scope.$watch(function () {
            TweenMax.to($element, .5, {borderColor: tinycolor.fromRatio({
                r: Math.random(),
                g: Math.random(),
                b: Math.random()
            }).toHexString()})

        })
    })

    .directive("digestButton", function ($rootScope) {
        return {
            restrict: "E",
            template: "<button class='btn'>$digest {{digestCount}}</button>",
            link: function (scope, element, attrs, ctrl) {
                scope.digestCount = 0;
                element.on("click", function () {
                    $rootScope.time = moment().format('h:mm:ss');
                    scope.digestCount++;
                    scope.$digest();
                })
            }
        }
    })

    .directive("applyButton", function ($rootScope) {
        return {
            restrict: "E",
            template: "<button class='btn'>$apply {{applyCount}}</button>",
            link: function (scope, element, attrs, ctrl) {
                scope.applyCount = 0;
                element.on("click", function () {
                    $rootScope.time = moment().format('h:mm:ss');
                    scope.applyCount++;
                    scope.$apply();
                })
            }
        }
    })

参考

http://stackoverflow.com/questions/18697745/apply-vs-digest-in-directive-testing http://stackoverflow.com/questions/13743058/how-to-access-the-angular-scope-variable-in-browsers-console