3

Angular Dart 教程的主要运行示例是一个食谱书应用程序第 5 章末尾关于过滤器和服务的练习建议尝试“创建一个 [自定义] 过滤器,它将食谱中 [列出的每种成分] 的所有数量相乘”,从而允许“用户翻倍、三倍或把食谱翻两番。” 例如,“1/2 杯面粉”的成分在翻倍时会变成“1 杯面粉”。

我编写了这样一个自定义过滤器:它需要一个Ingredients 列表(由 aquantity和 a组成description)并返回一个新的 new Ingredients 列表(数量增加),但我收到以下错误:

5 $digest() iterations reached. Aborting!

我的问题是:AngularDart 自定义过滤call()方法的要求和/或允许的行为是什么?例如,显然允许从其输入列表中删除(即过滤)元素,但它也可以添加新元素或替换元素吗?Dart angular.core NgFilter文档只是说“过滤器是一个带有调用方法的类”。我还没有找到更多细节。

从这个 AngularJS 帖子的答案推断,似乎重复调用call()应该(最终?)产生“相同的结果”。如果是这样,这将是一个合理的约束。

产生“相同的结果”可能意味着call()需要是幂等的,但在 Dart 的情况下,这种幂等性应该是相对于==(对象等价)而不是identical()(对象身份),恕我直言。我使用以下小示例进行了一些测试来说明问题:

  • 主要.dart
    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());
  • index.html 摘录
    <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被考虑==过,那么 call()main.dart 中的第二个实现(带有 的那个add(new A()))仍然会给出一个错误(尽管是一个不同的)。

我可以看到如何在不使用自定义过滤器的情况下解决教程练习,但我试图不放弃寻找可以按要求工作的过滤器的挑战。我是 Angular 的新手,并决定加入 AngularDart,因此在解释 的各种风格的效果call()或查找 , 的预期行为的文档方面有任何帮助call()(或者让我知道您是否认为这样的自定义过滤器根本无法被写!)将不胜感激。

4

1 回答 1

5

迭代次数过多

当 angular 检测到模型的变化时,它会执行一个反应函数。反应函数可以进一步改变模型。这将使模型处于不一致的状态。出于这个原因,我们重新运行更改检测,这可以进一步创建更多更改。出于这个原因,我们不断重新运行更改,直到模型稳定。但是在放弃之前我们应该重新运行多少次变更检测呢?默认为 5 次。如果模型在 5 次迭代后不稳定,我们就放弃。这就是你的情况。

变化检测

什么时候改变了对象?可以使用identical==(等于)。可以为每个提出好的论据,但我们选择使用identical它是因为它快速且一致。使用==(equals) 很棘手,它会对更改检测算法产生负面影响。

过滤器和数组

当操作数组的过滤器执行时,它别无选择,只能创建数组的新实例。这打破了相同的,但幸运的是,ng-repeat它使用自己的算法进行数组内容检测而不是数组检测。虽然数组在运行之间不必相同,但其内容必须相同。否则ng-repeat无法区分插入和更改,这需要做适当的动画。

你的代码

您的过滤器的问题在于它会在摘要循环的每次迭代中创建新实例。这些新实例会阻止模型稳定并因此导致错误。(有解决这个问题的计划,但我们要过几周才能到达那里。)

解决方案

您的解决方案正在尝试创建一个使用整个数组的过滤器,然后尝试为ng-repeat. 一个不同的(首选)解决方案是让ng-repeat迭代保持原样,而是将过滤器放在创建数量的绑定上并将其应用到那里。

<span>{{recipe.qty | myFilter:multiply}}</span>
于 2014-01-27T04:48:51.280 回答