2

我正在阅读这The Complete Book on AngularJS, Ari Lerner本书,并在 ng-class 上找到了这个示例。generateNumber()我在函数内部添加了一个额外的 console.log 。我看到它只记录了一次。

x之后我用generateNumber()函数调用替换了使用的地方。在我的更改看到这个之后,我的代码看起来像这样:

HTML

<!doctype html>
<html ng-app="myApp">
<head>
  <link rel="stylesheet" href="//cdn.jsdelivr.net/foundation/4.3.2/css/foundation.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.js"></script>
</head>
<body>

<div ng-controller="LotteryController">
  <div ng-class="{red: generateNumber() > 5}">
    You won!
  </div> 
  <button ng-click="generateNumber()">Draw Number</button>
  <p>Number is: {{ x }}</p>
</div>

</body>
</html>

JS

angular.module('myApp', [])
.controller('LotteryController', function($scope) {
  $scope.generateNumber = function() {
    var num = Math.floor((Math.random()*10)+1);
    console.log("Number: "+num);
    $scope.x = num;
    return num;
  };
});

所以我无法理解为什么console.log()被记录了很多次,即使我单击按钮它应该只记录一次但它被记录了多次。我无法理解为什么多次调用该方法。有时我也会遇到这个异常(我只粘贴了前两行)

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations:

这个 $digest 是干什么用的?以及为什么它达到了极限。什么是观察者?并请说明为什么要进行多次记录?谢谢你们,

编辑

感谢大家的回复,但我想使用类似ng-class="{red: generateNumber() > 5}"What is wrong 这样的东西。有人可以解释一下吗?我不想在$scope.x那里使用,所以你们现在可以忽略它。

谢谢你们,

4

4 回答 4

1

可能在每个摘要中都会验证 ng-class,然后您调用一个方法,以便在循环中调用它。

要更正:将您的 x 添加到范围变量,然后调用生成编号来初始化您的 x

**HTML:**

<div ng-controller="LotteryController">
  <div ng-class="{'red': x > 5}" ng-init="generateNumber()">
    You won!
  </div> 
  <button ng-click="generateNumber()">Draw Number</button>
  <p>Number is: {{ x }}</p>
</div>
于 2015-08-24T13:49:45.980 回答
1

在每个 $scope.$digest 调用 console.log,因为您使用方法 $scope.generateNumber 作为 ng-class 的条件,内部 generateNumber() 修改 $scope.x 变量导致新的 $digest 循环运行。

在每个 $digest 周期调用生成编号以确定是否应用该类。

使用 $scope.x 作为 ng-class 的条件

angular.module('myApp', [])
.controller('LotteryController', function($scope) {
  $scope.generateNumber = function() {
    var num = Math.floor((Math.random()*10)+1);
    console.log("Number: "+num);
    $scope.x = num;
    return num;
  };
});
<!doctype html>
<html ng-app="myApp">
<head>
  <link rel="stylesheet" href="//cdn.jsdelivr.net/foundation/4.3.2/css/foundation.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.js"></script>
</head>
<body>

<div ng-controller="LotteryController">
  <div ng-class="{red: x > 5}">
    You won!
  </div> 
  <button ng-click="generateNumber()">Draw Number</button>
  <p>Number is: {{ x }}</p>
</div>

</body>
</html>

于 2015-08-24T13:58:40.423 回答
1

根据文档

处理当前范围及其子范围的所有观察者。因为观察者的侦听器可以更改模型,所以 $digest() 会不断调用观察者,直到没有更多的侦听器被触发。这意味着有可能进入无限循环。此函数将抛出“超出最大迭代限制”。如果迭代次数超过 10。

换句话说,$digest是您的视图与 $scope 同步的过程。摘要开始后,它会循环,直到与前一个循环中的状态$scope相比,它的状态没有改变。

范围状态的更改是通过评估监视表达式(明确定义或在您的视图中隐含)来确定的。如果每个表达式在连续循环中计算出相同的结果,则摘要将结束。

为了具体解决您的观察,请generateNumber()始终返回一个新数字!所以$digest过程总是看到范围的状态在每个周期结束时发生变化。经过 10 个周期后,系统猜测它处于无限循环中,因此它抛出了您观察到的异常(以及文档中指定的)。

您可以按照以下方法解决问题:

$scope.generateNumber = function () {
    $scope.x = Math.floor((Math.random() * 10) + 1);
    console.log("Number: " + $scope.x);
};

接下来,应对您的标记进行以下更改:

  <div ng-class="{red: x > 5}">
    You won!
  </div>

正如我在您的一条评论中看到您所说的“我不想直接使用 x ”;那么创建一个返回类映射对象的方法就足够了,或者直接将类映射对象添加到作用域,或者添加一个将生成的数字返回到作用域的方法。

1.添加一个将生成的数字返回到作用域的方法

JS:

var number;
$scope.getNumber = function () {
    return number;
};
$scope.generateNumber = function () {
    $scope.x = Math.floor((Math.random() * 10) + 1);
    number = $scope.x;
    console.log("Number: " + $scope.x);
};

HTML

  <div ng-class="getNumber() > 5">
    You won!
  </div>

2.使用返回类映射对象的方法

JS:

var classMap = {};
$scope.getClassMap = function () {
    classMap.red = $scope.x > 5;
    return classMap;
};

HTML

  <div ng-class="getClassMap()">
    You won!
  </div>

3.直接将class map对象加入scope

JS:

$scope.classMap = {};
$scope.generateNumber = function () {
    $scope.x = Math.floor((Math.random() * 10) + 1);
    $scope.classMap.red = $scope.x > 5;
    console.log("Number: " + $scope.x);
};

HTML

  <div ng-class="classMap">
    You won!
  </div>
于 2015-08-24T14:18:18.960 回答
0

您在 ng-class 和 ng-click 中调用 generateNumber() 两次,这就是它多次记录的原因。查看 ng-class 的变化:

angular.module('myApp', [])
.controller('LotteryController', function($scope) {
  $scope.generateNumber = function() {
    var num = Math.floor((Math.random()*10)+1);
    console.log("Number: "+num);
    $scope.x = num;
    return num;
  };
});
<!doctype html>
<html ng-app="myApp">
<head>
  <link rel="stylesheet" href="//cdn.jsdelivr.net/foundation/4.3.2/css/foundation.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.js"></script>
</head>
<body>

<div ng-controller="LotteryController">
  <div ng-class="{red: x > 5}">
    You won!
  </div> 
  <button ng-click="generateNumber()">Draw Number</button>
  <p>Number is: {{ x }}</p>
</div>

</body>
</html>

于 2015-08-24T13:52:48.960 回答