【问题标题】:Is the $scope.$apply() call warranted for this scenario?对于这种情况,是否需要调用 $scope.$apply() ?
【发布时间】:2015-12-08 04:14:34
【问题描述】:

AngularJS(坦率地说是 JavaScript)的新手,但从我收集的信息来看,只有在 Angular 的雷达之外发生更改时才需要显式调用 $scope.$apply()。下面的代码(从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);
  };
}]);

【问题讨论】:

    标签: javascript angularjs angularjs-scope angularjs-service angularjs-digest


    【解决方案1】:
    setTimeout(function() { callback(siteList); }, 2000);
    

    这一行将带您脱离 Angular 的摘要循环。您可以简单地将 setTimeout 替换为 Angular 的 $timeout 包装器(您可以将其注入到您的 DataStore 服务中),并且您不需要 $scope.$apply

    【讨论】:

      【解决方案2】:

      setTimeoutasync 事件,它被视为超出angular 上下文,因此它不会运行摘要循环。执行此类操作时需要手动运行它,但首选使用$timeout

      相反,angular 确实提供了$timeout 服务,其工作方式与setTimeout 相同,但在执行回调函数后它会调用$scope.$apply()

      $timeout(function() { callback(siteList); }, 2000);
      

      $timeout 的特别之处在于它运行摘要循环 更安全的方式。它给你一个保证,它不会与任何冲突 当前正在运行摘要循环。在幕后,当您在$timeout 中调用函数时,它会通过检查$scope.root.$$phase 来检查是否有任何摘要循环在运行,如果它处于digest 阶段,它将将该摘要循环放入队列并运行它完成该消化周期后。

      【讨论】:

        猜你喜欢
        • 2011-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多