我知道范围观察者和过滤器都在摘要循环中重复执行。但是,以下内容对我来说有点不清楚:
它们是否执行相同数量的周期?
两者都是由相同的情况触发的吗?
我知道范围观察者和过滤器都在摘要循环中重复执行。但是,以下内容对我来说有点不清楚:
它们是否执行相同数量的周期?
两者都是由相同的情况触发的吗?
每个摘要周期都会检查手表。并且 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
再一次是检查该结果是否需要传播。如果该传播导致任何更改,则监视和过滤器将再次运行,直到没有任何更改。
而且,当然,如果多个观察表达式使用相同的过滤器,那么该过滤器将按照上述对每个表达式运行。