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 isslower
(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