3

我知道范围观察者和过滤器都在摘要循环中重复执行。但是,以下内容对我来说有点不清楚:

  • 它们是否执行相同数量的周期?

  • 两者都是由相同的情况触发的吗?

4

1 回答 1

7

每个摘要周期都会检查手表。并且 a$watch可以观看Angular 表达式。在表达式内部可以有一个过滤器,Angular 必须评估(使用$interpolate)来确定监视的表达式是否已更改。

两者都是由相同的情况触发的吗?

因此,过滤器不是直接运行的,$digest而是作为$watch. 实际上,过滤器是由监视表达式的评估触发的。

关于$digest. 看这两个表达式:

表达式 1:{{searchText+2}}

表达式 2:{{searchText | myFilter:true}}

$digest每次触发a 时都会评估这两个表达式。因此,一个风险区域很简单,它myFilter可能很复杂,并且最终会使用比简单的东西更多的处理器周期(如上面的 +2)。

不太明显的是,如果过滤器不是幂等的,它可能会导致所有观察者的额外运行。$digest如果任何监视导致更改,则在每次运行时都会设置一个脏位。如果设置了该脏位,它会再次重新运行所有手表。这允许传播任何更改。例如,如果searchText其中一个手表改变了,那么 Angular 需要给所有其他观察者一个机会,看看他们的结果是否依赖于searchText并因此应该改变。

这就是上面表达式 1 和 2 之间的区别。作为最坏的情况,想象myFilter返回一个随机数。 $digest运行,在评估监视时看到更改(过滤器的先前结果与新结果不匹配),因此它再次遍历监视列表。因为过滤器返回一个随机数,所以它的结果很可能已经改变,触发了又一次运行$digest. 等等,等等...... Angular 在 10 次循环通过它的观察列表后有一个内置停止 - 它会计算出如果在 10 次尝试后结果不稳定,那么就会出现问题,因此它放弃抛出“错误:10 $digest()达到迭代次数。中止!

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

因此,每个被监视的表达式(包括任何过滤器)至少运行两次$digest。一次是因为触发的更改,$digest再一次是检查该结果是否需要传播。如果该传播导致任何更改,则监视和过滤器将再次运行,直到没有任何更改。

而且,当然,如果多个观察表达式使用相同的过滤器,那么该过滤器将按照上述对每个表达式运行。

于 2014-01-15T19:44:49.493 回答