AngularJS digest循环中如何处理观察者和过滤器?

3

我知道作用域监视器和过滤器都是在脏检查循环中重复执行的。但以下内容对我有点不清楚:

  • 它们执行的循环次数相同吗?

  • 它们都是由相同的情况触发的吗?

1个回答

7
每个摘要周期都会检查手表。一个$watch可以观察Angular 表达式。在一个表达式中,可以有一个过滤器,Angular 必须评估它(使用$interpolate)以确定观察的表达式是否已更改。
这两者是由相同的情况触发的吗?
因此,过滤器不是直接由$digest运行的,而是作为$watch评估表达式的结果运行的。实际上,过滤器是通过评估所观察的表达式来触发的。
关于$digest性能问题,过滤器有几个特殊的原因需要讨论。看一下这两个表达式:
表达式1:{{searchText+2}} 表达式2:{{searchText | myFilter:true}} 每次触发$digest时,两个表达式都将被评估。因此,一个风险领域就是myFilter可能会很复杂,并且最终使用比某些简单内容(如上面的+2)更多的处理器周期。
稍微不那么明显的是,如果过滤器不是幂等的,则可能导致所有监视程序的额外运行。在每次$digest运行时,如果任何监视结果发生更改,则会设置一个脏标志。并且如果设置了该脏位,则会重新运行所有监视器。这允许传播任何更改。例如,如果其中一个监视器更改了searchText,则Angular需要让所有其他监视器有机会查看它们的结果是否取决于searchText,从而应发生更改。
这里是上述表达式1和2之间的区别。最坏情况下,想象一下myFilter返回一个随机数。当评估观察器时(过滤器的先前结果与新结果不匹配),$digest运行并检测到更改,因此它再次运行观察列表。由于过滤器返回一个随机数,其结果很可能已经改变,从而触发了$digest的另一次运行等等... Angular在遍历其观察列表10次后内置停止-如果结果在10次尝试后不稳定,则认为出现问题,因此放弃并抛出“错误:达到10个$digest()迭代。中止!”

它们执行相同数量的周期吗?

因此,每个观察表达式(包括任何过滤器)至少在每个$digest中运行两次。一次是因为触发了$digest的更改,另一次是为了检查该结果是否需要传播。如果该传播导致任何更改,则会重新运行观察器和过滤器,直到没有任何变化。

当然,如果多个观察表达式使用同一个过滤器,则该过滤器将按照上述方式为每个表达式运行。


非常棒的解释,谢谢。很抱歉,在我提问后不久就得到了你的答案,但是我只是简单地忘记了接受它! - luisfarzati

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接