Angular Dart教程的主要运行示例是食谱书应用。 Chapter 5 on filters and services结束时的练习建议尝试" 创建一个[自定义]过滤器,它将使[食谱中列出的每种成分]的所有数量相乘&#34 ;从而允许" 用户将食谱加倍,三倍或四倍。"例如。 " 1/2杯面粉的成分"将成为" 1杯面粉"加倍的时候。
我编写了这样一个自定义过滤器:它包含Ingredient
个列表(包含quantity
和description
)并返回新的{{1}列表} s(数量增加),但我收到以下错误:
Ingredient
我的问题是: AngularDart自定义过滤器5 $digest() iterations reached. Aborting!
方法的必需和/或允许行为是什么?例如,显然允许从其输入列表中删除(即过滤)元素,但是它是否还可以添加新元素或替换元素? Dart angular.core NgFilter文档只是说"过滤器是一个带调用方法的类"。我还没有找到更多细节。
从this AngularJS post的答案推断,似乎call()
的重复调用应该(最终?)产生"相同的结果"。如果是这样,这将是一个合理的约束。
屈服"同样的结果"可能意味着call()
需要幂等,但在Dart的情况下,这种幂等性应该相对于call()
(对象等价)而不是==
(对象身份) ), 恕我直言。我使用以下小例子运行了一些测试来说明问题:
identical()
import 'package:angular/angular.dart';
class A { }
@NgFilter(name:'myFilter') class MutatingCustomFilter {
final A _a = new A();
call(List list) => new List.from(list)..add(_a); // runs ok.
// call(List list) => new List.from(list)..add(new A()); // gives error
}
class MyAppModule extends Module {
MyAppModule() { type(MutatingCustomFilter); }
}
main() => ngBootstrap(module: new MyAppModule());
如果我将 <ul>
<li ng-repeat="x in [1,2,3] | myFilter">{{x}}</li>
</ul>
的正文更改为
class A
使@override bool operator==(other) => true;
@override int get hashCode => 1;
的所有实例都被视为A
,然后main.dart(==
中的call()
的第二个实现仍然会出错(尽管另一个)。
我可以看到如何在不使用自定义过滤器的情况下解决教程练习,但我试图不放弃寻找可按要求工作的过滤器的挑战。我是Angular的新手并且决定加入AngularDart,所以任何帮助解释add(new A())
的各种风格的影响,或者找到call()
的预期行为的文档,(或让我知道你是否认为这样的自定义过滤器根本无法编写!)将不胜感激。
答案 0 :(得分:5)
当角度检测到模型发生变化时,它会执行反应功能。反应函数可以进一步改变模型。这会使模型处于不一致状态。出于这个原因,我们重新运行更改检测,这可以进一步创建更多更改。因此,我们会继续重新运行更改,直到模型稳定下来。但是在放弃之前我们应该多少次重新检查变化检测?默认情况下是5次。如果模型在5次迭代后没有稳定,我们放弃。这就是你的情况。
何时更改了对象?可以使用identical
或==
(等于)。可以为每个人提供良好的论据,但我们选择使用identical
因为它快速且一致。使用==
(等于)很棘手,它会对变化检测算法产生负面影响。
当一个操作数组的过滤器执行它时别无选择,只能创建一个新的数组实例。这打破了相同的,但幸运的是它被送入ng-repeat
,它使用自己的算法进行数组内容检测而不是数组检测。虽然阵列在运行之间不必相同,但其内容必须是。否则ng-repeat
无法区分插入和更改之间的区别,它需要做适当的动画。
您的过滤器的问题是它在摘要循环的每次迭代中创建新实例。这些新实例会阻止模型稳定并因此导致错误。 (有计划解决这个问题,但是在我们到达那里之前几周。)
您的解决方案正在尝试创建一个过滤器,该过滤器使用整个阵列,然后尝试为ng-repeat
创建一个新阵列。一个不同的(首选)解决方案是按原样保留ng-repeat
迭代,而是将过滤器放在创建数量的绑定上并将其应用于那里。
<span>{{recipe.qty | myFilter:multiply}}</span>