手动触发ngOnChanges方案

840 阅读1分钟
// 数组
class RenderIterableChange<T> {
  private _differ: IterableDiffer<T>;
  private data: NgIterable<T>;
  private change$: Subject<IterableChanges<T>> = new Subject();

  constructor(
    // 数据
    data: { [key: number]: any },
    // 变化
    private _differs: IterableDiffers
  ) {
    // 初始化时先执行一次changes
    this.doChanges(data, true);
  }

  private doCheck(): void {
    if (this._differ) {
      let changes = this._differ.diff(this.data);
      if (changes) {
        // 变化监听
        this.change$.next(changes);
      }
    }
  }
  // 首次调用一次 之后每次变化调用
  doChanges(data: any, isFirst: boolean = false): void {
    // 如果不是首次变化 先检测变化
    if (!isFirst) {
      this.doCheck();
    }
    this._differ = this._differs.find(data).create();
    this.data = data;
    // 如果是首次变化 后检测变化
    if (isFirst) {
      this.doCheck();
    }
  }

  onChanges(): Subject<IterableChanges<T>> {
    return this.change$;
  }
}
// key-value
class RenderKeyValueChange<T> {
  private _differ: KeyValueDiffer<string, T>;
  private data: { [key: string]: T };
  private change$: Subject<KeyValueChanges<string, any>> = new Subject();
  constructor(
    // 数据
    data: { [key: string]: T },
    // 变化
    private _differs: KeyValueDiffers
  ) {
    // 初始化时先执行一次changes
    this.doChanges(data, true);
  }
  private doCheck(): void {
    if (this._differ) {
      let changes = this._differ.diff(this.data);
      if (changes) {
        // 变化监听
        this.change$.next(changes);
      }
    }
  }
  // 首次调用一次 之后每次变化调用
  doChanges(data: any, isFirst: boolean = false): void {
    // 如果不是首次变化 先检测变化
    if (!isFirst) {
      this.doCheck();
    }
    this._differ = this._differs.find(data).create();
    this.data = data;
    // 如果是首次变化 后检测变化
    if (isFirst) {
      this.doCheck();
    }
  }
  // 监听变化
  onChanges(): Subject<KeyValueChanges<string, T>> {
    return this.change$;
  }
}
  • use

监听object变化

let a = { i: 2 };
let b = { i: 2 };
let c = { i: 2 };
let d = { i: 2 };
let list = { a: a, b: b, c: c, d: d };
let change = new RenderKeyValueChange(list, this._differs);
change.change$.subscribe(res => {
  console.log(res);
});
a.i = 333;
list.a = c;
change.onChanges(list);

监听数组变化

let a = { i: 2 };
let b = { i: 2 };
let c = { i: 2 };
let d = { i: 2 };
let list = [a, b, c, d];
let change = new RenderIterableChange(list, this._iterableDiffers);
change.onChanges().subscribe(res => {
  // 改变监听
  console.log(res);
});
a.i = 333;
list[1] = c;
change.doChanges(list);

缺点,只能检测引用变化,不能检测真实值的改变 下面着手优化一下。