Javascript 使用'时出现意外的角度行为;警报';

Javascript 使用'时出现意外的角度行为;警报';,javascript,angularjs,Javascript,Angularjs,我正在学习/实验angular,偶然发现了一些奇怪的行为(在我看来)。我用尽可能小的示例重新创建了我的问题-原始代码要长得多 我想让它做什么: 用户可以输入名称。当名称等于“error”时,其颜色将变为红色并显示警报。当用户解除警报(单击“确定”)时,名称将重置为“初始名称”,并再次变为绿色 它没有做什么: 当名称变为“错误”时,其颜色不是红色 代码: <html lang="en-US" ng-app="myApp" ng-controller="myCtrl"> <s

我正在学习/实验angular,偶然发现了一些奇怪的行为(在我看来)。我用尽可能小的示例重新创建了我的问题-原始代码要长得多

我想让它做什么:
用户可以输入名称。当名称等于“error”时,其颜色将变为红色并显示警报。当用户解除警报(单击“确定”)时,名称将重置为“初始名称”,并再次变为绿色

它没有做什么:
当名称变为“错误”时,其颜色不是红色

代码:

<html   lang="en-US" ng-app="myApp" ng-controller="myCtrl">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body>
    <div>
        <input ng-model="name" ng-style="{color: myColor}"/>
    </div>
</body>

<script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope, $document) {
        $scope.name = "initial name";
        $scope.myColor = "green";
        $scope.$watch('name', function() {
            if($scope.name === "error") {
                $scope.myColor = "red"; // This line has no effect?
                alert("Not allowed! Resetting...");
                $scope.name = "initial name";
            } else {
                $scope.myColor = "green";
            }
        });
    });
</script>

var-app=angular.module('myApp',[]);
app.controller('myCtrl',函数($scope,$document){
$scope.name=“初始名称”;
$scope.myColor=“绿色”;
$scope.$watch('name',function(){
如果($scope.name==“error”){
$scope.myColor=“red”//此行无效吗?
警报(“不允许!正在重置…”);
$scope.name=“初始名称”;
}否则{
$scope.myColor=“绿色”;
}
});
});

我知道更改
$scope.myColor
应该会更改颜色(如果我删除else子句,它将永远保持红色),但出于某种原因,
警报似乎阻止了所需的行为。我还更改了if子句中的行顺序,但这没有帮助

问题:
有没有天才能解释为什么“错误”不会变成红色?

(我真的不需要解决方案,我只想知道为什么会发生这种情况。)

alert
阻止所有脚本执行,并在摘要完成之前触发

在一个有角度的应用程序中使用它并不是一件好事,它在引擎盖下做的事情与在普通页面中做的事情有很多不同


我建议您使用javascript驱动的警报系统。此功能有许多可用的角度模块

,因为您将手表内的值更新为红色,但也会直接更改名称,之后将再次触发对手表的回调,并立即将其更改回绿色。在警报可见期间,您可能会期望文本为红色,但由于您仍在手表内且摘要周期为“暂停”(由于警报),因此您将看不到这一点。

alert()
是一个阻塞调用,它会阻塞所有其他内容,直到它被解除为止。因此,
$scope.myColor
将更改为红色,但在角度摘要循环完成之前,会弹出警报并阻止所有其他内容。一旦解除警报,名称将重置,颜色将恢复正常


因为每件事都是以毫秒为单位发生的,所以你无法看到它。因此,如果您将警报设置为1-2秒超时,您应该能够看到错误的红色。

如其他人所述,
警报
会阻止所有处理,直到关闭
警报。您可以使用另一个系统,例如ui引导中的
$modal
(您可能想这样做),但如果您绝对想使用
警报
,则可以使用
设置超时/$timeout
来确保
警报
发生在下一个
$digest
周期的开始

$timeout(function() {
  alert('hello, world')
}, 0)

但是,这并不能保证按照您想要的顺序执行,因此我建议您使用ui引导或其他人建议的类似方法。

Angular并不总是遵循
$scope
的所有字段。它的功能-它不时运行
$digest
。在这种情况下,
$watch
函数主体完成后


因此,在本例中,您更改了字段,显示了警报,在关闭警报后,它更改了名称,启动了
$digest
,再次启动了此函数。

Angular的工作方式可能看起来是实时的,但实际上是通过收集对“关注”变量的所有更改,然后将其应用于视图来工作的。在$watch中,在代码结束之前无法应用更改,但警报会暂停执行。见:

您可以通过执行以下操作来解决此问题:

<html   lang="en-US" ng-app="myApp" ng-controller="myCtrl">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body>
    <div>
        <input ng-model="name" ng-style="{color: myColor}"/>
    </div>
</body>

<script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($timeout, $scope, $document) {
        $scope.name = "initial name";
        $scope.myColor = "green";
        $scope.$watch('name', function() {
            if($scope.name === "error") {
              $timeout(function(){
                $scope.myColor = "red"; // This line has no effect?
                alert("Not allowed! Resetting...");
                $scope.name = "initial name";
              });
            } else {
                $scope.myColor = "green";
            }
        });
    });
</script>

var-app=angular.module('myApp',[]);
app.controller('myCtrl',函数($timeout,$scope,$document){
$scope.name=“初始名称”;
$scope.myColor=“绿色”;
$scope.$watch('name',function(){
如果($scope.name==“error”){
$timeout(函数(){
$scope.myColor=“red”//此行无效吗?
警报(“不允许!正在重置…”);
$scope.name=“初始名称”;
});
}否则{
$scope.myColor=“绿色”;
}
});
});

根据作用域生命周期的描述,这是由于脏检查造成的

您的作业
$scope.myColor=“绿色”在$watch中更改模型的值,进一步启动$digest。
警报()

计算表达式后,$apply方法执行$digest。 在$digest阶段,作用域检查所有$watch表达式 并将其与以前的值进行比较。这个肮脏的检查已经完成了 异步的。这意味着分配,例如 $scope.username=“angular”不会立即导致$watch被删除 通知,$watch通知将延迟到$digest 阶段。这种延迟是可取的,因为它合并了多个模型 更新为一个$watch通知,并保证在 $watch通知没有其他$watch正在运行。如果是一块美元的手表 如果更改模型的值,则将强制附加$digest 循环


好吧,有时候棱角并不能像你们期望的那个样消化,你们必须用力
$timeout(function(){
    //Your content here
});
$scope.apply(function(){
    //Your content here
});