$scope.$apply() 调用是否适合这种情况?
Is the $scope.$apply() call warranted for this scenario?
AngularJS 的新手(和 JavaScript 坦率地说),但根据我收集到的信息,只有在 [= 之外发生更改时才需要显式调用 $scope.$apply() 21=]的雷达。下面的代码(从 this plunker 粘贴)让我认为这不是需要调用的情况,但这是我让它工作的唯一方法。我应该采取其他方法吗?
index.html:
<html ng-app="repro">
<head>
...
</head>
<body class="container" ng-controller="pageController">
<table class="table table-hover table-bordered">
<tr class="table-header-row">
<td class="table-header">Name</td>
</tr>
<tr class="site-list-row" ng-repeat="link in siteList">
<td>{{link.name}}
<button class="btn btn-danger btn-xs action-button" ng-click="delete($index)">
<span class="glyphicon glyphicon-remove"></span>
</button>
</td>
</tr>
</table>
</body>
</html>
script.js:
var repro = angular.module('repro', []);
var DataStore = repro.service('DataStore', function() {
var siteList = [];
this.getSiteList = function(callback) {
siteList = [
{ name: 'One'},
{ name: 'Two'},
{ name: 'Three'}];
// Simulate the async delay
setTimeout(function() { callback(siteList); }, 2000);
}
this.deleteSite = function(index) {
if (siteList.length > index) {
siteList.splice(index, 1);
}
};
});
repro.controller('pageController', ['$scope', 'DataStore', function($scope, DataStore) {
DataStore.getSiteList(function(list) {
$scope.siteList = list; // This doesn't work
//$scope.$apply(function() { $scope.siteList = list; }); // This works
});
$scope.delete = function(index) {
DataStore.deleteSite(index);
};
}]);
setTimeout(function() { callback(siteList); }, 2000);
此行将带您离开 Anglar 的摘要循环。您可以简单地将 setTimeout
替换为 Angular 的 $timeout
包装器(您可以将其注入您的 DataStore 服务),并且您不需要 $scope.$apply
.
setTimeout
是 async
事件,被视为超出 angular
上下文,因此它不 运行 摘要周期。当你做这样的事情时,你需要手动 运行 它,但更喜欢使用 $timeout
.
相反,angular 确实提供了一个 $timeout
服务,其工作方式与 setTimeout
相同,但在执行回调函数后,它会调用 $scope.$apply()
$timeout(function() { callback(siteList); }, 2000);
Special thing about the $timeout
is that it runs the digest cycle in
safer way. It gives you a guarantee that it will not conflict with any
currently running digest cycle. Behind the scenes, when you call function inside the $timeout
, it checks whether there is any digest cycle running or not by checking $scope.root.$$phase
, if it's in the digest
phase, it places that digest cycle in queue and runs it after completion of that digest cycle.
AngularJS 的新手(和 JavaScript 坦率地说),但根据我收集到的信息,只有在 [= 之外发生更改时才需要显式调用 $scope.$apply() 21=]的雷达。下面的代码(从 this plunker 粘贴)让我认为这不是需要调用的情况,但这是我让它工作的唯一方法。我应该采取其他方法吗?
index.html:
<html ng-app="repro">
<head>
...
</head>
<body class="container" ng-controller="pageController">
<table class="table table-hover table-bordered">
<tr class="table-header-row">
<td class="table-header">Name</td>
</tr>
<tr class="site-list-row" ng-repeat="link in siteList">
<td>{{link.name}}
<button class="btn btn-danger btn-xs action-button" ng-click="delete($index)">
<span class="glyphicon glyphicon-remove"></span>
</button>
</td>
</tr>
</table>
</body>
</html>
script.js:
var repro = angular.module('repro', []);
var DataStore = repro.service('DataStore', function() {
var siteList = [];
this.getSiteList = function(callback) {
siteList = [
{ name: 'One'},
{ name: 'Two'},
{ name: 'Three'}];
// Simulate the async delay
setTimeout(function() { callback(siteList); }, 2000);
}
this.deleteSite = function(index) {
if (siteList.length > index) {
siteList.splice(index, 1);
}
};
});
repro.controller('pageController', ['$scope', 'DataStore', function($scope, DataStore) {
DataStore.getSiteList(function(list) {
$scope.siteList = list; // This doesn't work
//$scope.$apply(function() { $scope.siteList = list; }); // This works
});
$scope.delete = function(index) {
DataStore.deleteSite(index);
};
}]);
setTimeout(function() { callback(siteList); }, 2000);
此行将带您离开 Anglar 的摘要循环。您可以简单地将 setTimeout
替换为 Angular 的 $timeout
包装器(您可以将其注入您的 DataStore 服务),并且您不需要 $scope.$apply
.
setTimeout
是 async
事件,被视为超出 angular
上下文,因此它不 运行 摘要周期。当你做这样的事情时,你需要手动 运行 它,但更喜欢使用 $timeout
.
相反,angular 确实提供了一个 $timeout
服务,其工作方式与 setTimeout
相同,但在执行回调函数后,它会调用 $scope.$apply()
$timeout(function() { callback(siteList); }, 2000);
Special thing about the
$timeout
is that it runs the digest cycle in safer way. It gives you a guarantee that it will not conflict with any currently running digest cycle. Behind the scenes, when you call function inside the$timeout
, it checks whether there is any digest cycle running or not by checking$scope.root.$$phase
, if it's in thedigest
phase, it places that digest cycle in queue and runs it after completion of that digest cycle.