Angular2 的管道如何与数据绑定一起工作?

How does Angular2's pipes work with data binding?

我正在编写一个简单的待办事项应用程序来学习 Angular 2. 我注意到使用管道会破坏更新行为。

我有以下模板

<input type="text" placeholder="Search" #queryBox (keyup)="query=queryBox.value">

<ul class="task-list">
    <task-item *ng-for="#task of tasks | filter:containsString:query" [task]="task" (onDelete)="delete($event)"></task-item>
</ul>

当我点击删除按钮时,底层数据模型发生了变化,但这种变化并未反映在 UI 中。我确定这是因为过滤管道没有被调用。如果我将上面的行更改为

<task-item *ng-for="#task of tasks" [task]="task" (onDelete)="delete($event)"></task-item>

然后添加、删除之类的操作再次起作用,但很明显我没有得到过滤。为什么添加管道会破坏此绑定的更新行为?

那是因为默认情况下管道是无状态的(它们只渲染 UI 一次).

您必须添加:

 @Pipe({
  selector: ...,
  pure: false
})

当您将 'pure' 设置为 false 时,Angular 每个周期都会更新管道内的数据。

默认情况下,管道是 stateless/pure。如果它们的输入没有变化,则管道不会在变化检测周期内执行。对于这个问题,我们有

"#task of tasks | filter:containsString:query"

taskscontainsStringquery是输入,管道filter是stateless/pure。
tasks是一个数组(参考)。

删除任务时,数组 reference 不会改变 – 管道的 tasks 输入不会改变 – 因此 stateless/pure 管道未执行。

如果我们使用 pure: false 使管道有状态,那么管道将在每个变化检测周期被评估——即使输入没有变化。

您可能还需要

  • 指定组件的onPush更改检测策略(如果可能),或
  • 实现管道的 transform() 方法,使其 returns 相同的数组(参考)。

对这些备选方案进行了详细解释 (我不想在这里重复所有内容)。