angular的ng-checked运行了两次

<body style="padding: 10px;" ng-app="app" ng-controller="MyCtrl">
    <input type="checkbox" ng-checked="check()">
</body>
<script src="node_modules/angular/angular.min.js"></script>
<script type="text/javascript">
    angular
        .module('app', [])
        .controller('MyCtrl',function($scope){
            var mm = 1;
            $scope.check = function(){
                console.log(mm)
                mm++;
            }
        })
</script>

如图所示,再浏览器中刷新页面的时候,发现check()运行了两次,不知道是哪里的原因

阅读 5.7k
4 个回答

angular 是基于脏检查更新视图。每次数据发生变化,至少需要两轮digest。为啥?数据发生变化,第一轮触发watches等;第二轮确保数据没有再发生变化,否则还会触发新一轮digest。

ng-checked会产生一个watch,初始化对表达式check()求值,数据发生变化(原先是没有值的)。于是,需要至少再一轮digest。如果check()返回mm,每次都有数据变化,那么会触发十轮digest,并且抛出一个错误:Infinite $digest Loop。因为digest默认连续触发最多十次。

官方文档对 ng-checked 对应的描述是

Sets the checked attribute on the element, if the expression inside ngChecked is truthy.

我理解ng-checked相当于给元素绑定了一个值,而不是像ng-click或者ng-blur这样的指令对应一个DOM事件。ng-checked绑定的表达式的值决定要不要给元素设置checked的属性。所以我对这个问题的理解是:只要angular触发脏值检查,ng-checked对应的方法都会被调用。

刷新页面就会执行?我看看控制台
http://www.runoob.com/angular...
ng-checked 指令用于设置复选框(checkbox)或单选按钮(radio)的 checked 属性。
如果 ng-checked 属性返回 true,复选框(checkbox)或单选按钮(radio)将会被选中。

多谢几位师兄的解答,通过一个实验,发现问题,发现还是和angular的脏循环有关,案例如下:

<body style="padding: 10px;" ng-app="app" ng-controller="MyCtrl">
    <input type="text" ng-model="msg" />
    <input type="checkbox" ng-checked="check(msg)">
    <div ng-click="change()">nnnnnn</div>
</body>
<script src="node_modules/angular/angular.min.js"></script>
<script type="text/javascript">

    angular
        .module('app', [])
        .controller('MyCtrl',function($scope){
            $scope.check = function(msg){
                if(msg == 4){
                    console.log(new Date()+'true')
                    return true;
                }else{
                    console.log(new Date()+'false')
                    return false;
                }
            }
            $scope.change = function(){
                $scope.msg  = 4;
            }
            $scope.$watch('msg',function(){
                console.log($scope.msg);
            })
        })
</script>

ng-checked触发了一次digest循环,会检查check()最后返回的值是否有变化,当他发现值变了,就会重新循环检查一次,来确认这个值有没有变化,这个过程中check()执行了两次,因此就有2次输出。
如同我例子中的,当我通过点击div,导致改变了$scope中的msg,而msg又是check()的重要参数,这个时候就导致check()返回值发生了变化,ng-click也会触发digest循环。这个时候他发现ng-checked的结果,也就是check()的结果发生了变化,更新view后,他就又重新执行check()检查ng-checked的值是否又变化了,因此,这又是输出了2次。
具体的浏览器输出,需要的师兄们请自行实验

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题