为什么 Angular 没有注意到这个变量的值发生了变化
Why doesn't Angular notice that this variable's value has changed?
我在一个非常简单的Angular应用程序上遇到了问题。这是一个代码笔;下面有相同的代码。
在这个应用程序中,你点击一个按钮吃香蕉,你吃过的香蕉总数会显示在页面上。每次点击后,应该有一秒钟的冷却时间,然后才能吃另一根香蕉。
为此,我做了以下工作:
-
$scope.cooling_down
是一个布尔值。 -
$scope.can_eat_banana
是一个返回true
或false
的函数,指示"吃香蕉"按钮是否应该可用。基本上,如果$scope.cooling_down
为假,则返回 true。 -
"吃香蕉"按钮有
ng-disabled="!can_eat_banana()"
。 -
当用户点击"吃香蕉"按钮时,我将
$scope.cooling_down
设置为true
,并使用window.setTimeout()
安排回调以将其设置为一秒后false
。
(你可能会问:为什么不完全摆脱$scope.can_eat_banana()
,而简单地使用按钮上的ng-disabled="cooling_down"
?答:因为,随着游戏的发展,决定玩家是否可以吃香蕉的逻辑会变得更加复杂。把这个逻辑放在视图中似乎真的很混乱。
因此,当我运行此测试用例时,会发生以下情况:
-
我加载页面。最初,该按钮处于启用状态。
-
我点击"吃香蕉"按钮。正如预期的那样,我的代码将
$scope.cooling_down
设置为true
,并且按钮被禁用。目前为止,一切都好。 -
一秒钟后,我传递到
window.setTimeout()
的回调触发了。(我有一个console.log()
作为回调的第一行,以确认它正在运行。此回调将$scope.cooling_down
设置回false
。(您可以查看控制台以确认值已更新。但:Angular 没有注意到该值已更改。该按钮不会重新启用,并且页面上的{{cooling_down}}
令牌将卡在true
上。
为什么?为什么 Angular 在第一次更改值时(当用户单击按钮后将其更改为 true
时)注意到,但第二次(当回调触发并将其设置回false
时)没有注意到?
<!DOCTYPE html>
<html ng-app="game">
<head>
<meta charset="utf-8">
<title>Incredibly Stupid Banana Game</title>
</head>
<body ng-controller="GameController">
<p>You have eaten {{bananas_eaten}} bananas.</p>
<button type="button" ng-click="eat_banana()" ng-disabled="!can_eat_banana()">Eat a Banana</button>
<p>[current value of cooling_down: {{cooling_down}}]</p>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
<script>
( function() {
var app = angular.module( "game", [] );
app.controller( "GameController", [ "$scope", function( $scope ) {
$scope.bananas_eaten = 0;
$scope.cooling_down = false;
$scope.eat_banana = function() {
$scope.bananas_eaten++;
$scope.cooling_down = true;
window.setTimeout( function() {
console.log( "setTimeout callback fired" );
$scope.cooling_down = false;
console.log( "Current value of cooling_down: " + $scope.cooling_down );
}, 1000 );
};
$scope.can_eat_banana = function() {
return !$scope.cooling_down;
};
} ] );
}() );
</script>
</body>
</html>
Angular 在window.setTimeout()
后不会再次运行其摘要循环(实际上,它甚至没有收到通知)。
请改用$timeout()
。
更新模型(范围的属性)时,必须进行摘要才能使该更改影响 UI。当 window.setTimeout 完成时,原始摘要(由单击引起)早已完成,另一个摘要未启动,因此 UI 永远不会更新。
若要解决此问题,请将window.setTimeout
替换为 $timeout
服务,该服务将在超时完成后启动另一个摘要。
- 值对象在某个变量发生更改后发生更改
- Javascript动态变量(添加了随机数)
- 重新加载页面时Javascript变量发生变化
- 存储区向变量返回了结果
- $scope变量发生更改时未触发Angular$watch
- 当变量发生变化时运行PHP
- 为什么属性存在于对象实例上,即使其原型发生了更改
- 服务变量分配了数据,但在访问时始终未定义
- Javascript函数 - 通过引用复制,但这里发生了什么
- 套接字发生了什么's在'断开连接'事件(服务器端)
- 这段代码中发生了什么
- Wamp没有识别出我的代码发生了更改
- 如何检查输入框值在使用淘汰之前是否发生了更改
- 通过它访问HTML元素's id DIRECTLY-这里发生了什么
- 为什么 Angular 没有注意到这个变量的值发生了变化
- 为什么我的变量“c”发生了变化
- 如果变量在settimeout之后但在它真正运行之前发生了变化怎么办?
- 如何动态检查Jquery变量是否发生了变化
- JavaScript -将名称空间分配给局部变量以用于构造函数,但不确定发生了什么
- 重写一个变量,旧的引用发生了什么