如何在不造成大量滞后的情况下观察一系列对象的变化?

How to watch for changes in an array of objects without causing massive lag?

我觉得 Angular 2 缺少 Angular 1 所具有的一些东西,其中之一就是 $watch 函数。

OnChangesDoCheck 应该替换 $watch 但我无法使用其中任何一个来获得所需的结果。 OnChanges 无法监听对象,因此在这种情况下没有用,虽然 DoCheck 完成了这项工作,但它会导致巨大的滞后,因为一旦发生变化它似乎就会变得疯狂。

这里我有一个组件,它有一堆复选框,每个复选框切换都会导致将一个值添加到数组,而不是默认的 true/false 功能。

在此组件中我需要注意的是复选框的 isDisabled 状态,因此每次更改时我都需要更新 checkboxisChecked 状态。

就像我说的,它有效,但它在每个复选框切换时都有 2-3 秒的延迟,尽管只有 5 个复选框。最好我不希望每次切换复选框时循环到 运行,而是仅当复选框的 isDisabled 状态发生变化时才循环。

编辑:有人告诉我 Observable 可以在这里完成这项工作,但我找不到任何将其应用于对象数组的示例,例如这个。它还需要在不手动调用其 next() 方法的情况下触发,因为它必须侦听对正在发送的数组的外部更改。

编辑 2:我创建了一个不显示延迟的 plunkr,可能是因为在我的应用程序中我还有其他可能对延迟有影响的东西。但是,plunkr 清楚地表明似乎有问题,因为我在 ngDoCheck() 函数中放置了一个 console.log(true) 并且它 运行 是很多次。这不是有意的,如果是,那就太奇怪了。

这里是 plunkr:https://plnkr.co/edit/dJVnqbrredDyWTXNDzDK?p=preview

我该怎么做?

export class FormCheckboxMultipleComponent implements OnInit, DoCheck {
  @Input() model: Array<any>;
  @Output('modelChange') onModelChange: EventEmitter<any> = new EventEmitter();
  @Output() callback: EventEmitter<any> = new EventEmitter();

  constructor(private _globals: GlobalVariablesService) {
    this.ns = _globals.ns;
  }

  ngOnInit() {
    this.model = this.model || [];
  }

  ngDoCheck() {

    for (let checkbox of this.checkboxes) {

      if (checkbox.isDisabled) {
        this.untoggle(checkbox);
      }
    }
  }

  findIndex(checkbox) {

    return this.model.reduce(function(cur, val, index) {

      if (val.name === checkbox.name && cur === -1) {
        return index;
      }

      return cur;
    }, -1);
  }

  addToModel(checkbox) {
    this.model.push(checkbox);
  }

  removeFromModel(i) {
    this.model.splice(i, 1);
  }

  toggle(checkbox) {

    if (checkbox.isDisabled) {
      return false;
    }

    let existingIndex = this.findIndex(checkbox);

    if (existingIndex === -1) {
      this.addToModel(checkbox);
    }
    else {
      this.removeFromModel(existingIndex);
    }

    checkbox.isChecked = !checkbox.isChecked;

    this.onModelChange.emit(this.model);

    this.callback ? this.callback.emit() : false;
  }

  untoggle(checkbox) {

    let existingIndex = this.findIndex(checkbox);

    this.removeFromModel(existingIndex);

    checkbox.isChecked = false;

    this.onModelChange.emit(this.model);
  }
}

这是由 ngDoCheck 中的 this.untoggle(checkbox) 中的 this.onModelChange.emit(this.model); 引起的。这是一个完美的无限循环。 this.onModelChange.emit(this.model); 导致更改检测,因此 ngDoCheck() 到 运行 并且循环再次开始。

确保更改检测不会导致更改检测。 ngDoCheck 由变更检测调用,不得调用另一个变更检测,否则会出现无限循环。

Plunker