究竟什么时候调用 ng-checked

When exactly is ng-checked called

在使用 AngularMaterial 时,我 ng-checked 是这样的:

<md-list>
    <md-list-item ng-repeat="option in options">
       <p> {{ option }} </p>
       <md-checkbox class="md-secondary" aria-label="{{$index}}" ng-checked="exists($index)" ng-click="toggle($index)"></md-checkbox>
    </md-list-item>
</md-list> 

我存在的函数:

$scope.exists = function (optionNum) {
    console.log('Inside $scope.exists. option: '+optionNum);
};

我的计时器:

function updateTimer() {
    var onTimeout = function(){
      mytimeout = $timeout(onTimeout,1000);
    }
    var mytimeout = $timeout(onTimeout,1000);
}

有了这个,$scope.exists 函数每秒都会被调用一次。有人可以解释一下 ng-checked$timeout 之间的关系吗?以及如何避免这种情况?

ng-checked,就像许多 angular 的指令一样,都是基于 watches 的。每当调用摘要循环时,它都会评估所有观察者(您正在使用的功能是其中之一)。所以每次 $timeout 评估它都会开始一个新的 $digest 循环并评估所有观察者。这是 "magic" 的一部分,它使视图使用控制器和指令中的所有数据进行更新。

如果您使函数变得复杂,或者创建大量观察者,观察者可能会成为性能问题。通常最好有简单的逻辑 returns true 或 false 非常快,并避免对所有内容设置监视。

原因一言以蔽之:digest cycle。由于您的函数绑定到视图,每次摘要循环发生时,这些表达式都会作为脏检查的一部分进行评估,以确保相应的 DOM 是否需要更新。这与 angular material 无关,它是核心 angular 实现。现在在你的情况下你正在无限地调用 $timeout 这意味着在每次超时执行后 digest 循环恰好执行脏检查。

现在你所拥有的很好,但是每当你 bind 函数到 DOM (作为视图绑定、插值或 属性 状态属性甚至 DOM 过滤器 - 当然事件很好)你应该 意识到这样一个事实,即随着应用程序的增长,你不会无意或有意地在该功能中执行大量操作 ,它会减慢整个应用程序,并且当应用程序变得更大并且问题开始发生时,将很难重构和诊断。尽可能绑定到 属性 而不是函数。请注意,即使您绑定 属性 仍然 angular $parse 在其上创建一个 getter 并将其添加到 $$watchers 队列以在每个摘要周期进行脏检查, 但区别在于它是一个简单的 getter 函数。

所以基本上,例如在您的情况下,您可以将 ng-checked 绑定到 属性

..ng-checked="doesExist"

并在需要更新时设置属性 doesExist。因此,您不必每次都检查是否存在,而是在相应事件发生时明确设置相应的 属性。这也使逻辑明确。