Angular 6中不纯管道的替代方案?

时间:2018-07-24 06:20:03

标签: angular typescript angular6

我正在尝试编写一个简单的待办事项应用程序以学习Angular6。在我的应用程序中,待办事项可以完成或未完成,我想在页脚组件中显示未完成的待办事项数量。

我有一个待办事项组件,显示待办事项列表:

todos.component.ts

export class TodosComponent implements OnInit {
  todos: Todo[];
  constructor(private todoService: TodoService) { 
    this.todos = todoService.GetAll();
  }
  ngOnInit() {}
  ToggleTodoCompleted(id: number): void{
    this.todoService.Toggle(id);
  }
}

要添加待办事项的另一个组件:

todo-add.component.ts

export class TodoAddComponent implements OnInit {
  constructor(private todoService: TodoService) { }
  ngOnInit() {}
  AddTodo(todoTitle){
    let todo = new Todo();
    todo.title = todoTitle;
    this.todoService.Add(todo);
  }
}

一个页脚组件,我使用一个不纯管道来显示其中未完成的待办事项的数量:

footer.component.ts

export class FooterComponent implements OnInit {
  todos: Todo[] = [];
  constructor(private todoService: TodoService) { 
    this.todos = todoService.GetAll();
  }
  ngOnInit() {}
}

uncompleted-todos.pipe.ts

@Pipe({
  name: 'uncompletedTodos',
  pure: false
})
export class UncompletedTodosPipe implements PipeTransform {

  transform(todos: Todo[]): any {
    return todos.filter(t=>t.completed===false);
  }
}

footer.component.html

{{(todos|uncompletedTodos).length}} items left

和简单的服务:

todo.service.ts

export class TodoService {
  private todos: Todo[] = [];
  GetAll(): Todo[]{
    return this.todos;
  }
  Add(todo: Todo): void{
    todo.id = this.todos.length + 1;
    todo.completed = false;
    this.todos.push(todo);
  }
  Toggle(id: number): void{
    let todo = this.todos.find(t => t.id === id); 
    todo.completed = !todo.completed;
  }
}

但是我在Angular文档中读到,不纯管道会导致性能问题。那么,另一种选择是什么呢?没有这种不纯净的管道,如何编写代码?

1 个答案:

答案 0 :(得分:1)

这是right in the documentation的解释:

  

Angular不提供用于过滤或排序列表的管道[...]这不是疏忽。 Angular不提供此类管道,因为它们性能不佳并阻止了积极的缩小[...] Angular团队和许多经验丰富的Angular开发人员强烈建议将过滤和排序逻辑移入组件本身

这意味着您应该摆脱管道,并将逻辑直接放入组件中。

例如

EDIT ,以将逻辑放入功能本身中:

export class TodoService {
  private todos: Todo[] = [];
  GetAll(): Todo[]{
    return this.todos;
  }
  GetUncompleted() {
    return this.todos.filter(td => !td.completed);
  }
  ...

编辑2 您的问题来自于在组件启动时仅分配一次待办事项的值。

这意味着将项目添加到待办事项列表时,您看不到更改,因为您没有更新值。

为此,有两种解决方案:第一种是使用吸气剂。

字母是特殊的函数,它们在被调用时都会更新其值。使用非常简单。例如,在您的todo.component中,它将给出:

get todos() { return this.todoService.getAll(); }

您现在可以通过

在模板中使用它
*ngFor="let todo of todos"

这将被更新。

Here is a stackblitz to show you how getters work

第二种解决方案是使用RxJS。这是一个事件解决方案:当列表更新时,您必须触发一个事件。由于此解决方案比较困难,因此我制作了this stackblitz来帮助您理解它。

基本上发生的是,每当您的列表更新时,您的组件都会收到一个事件,告诉他们必须更新待办事项列表。