Observable/subscrption 更改属性时 ngOnChanges 不触发

ngOnChanges not firing when attribute changed by Observable/subscrption

我正在尝试在 Observable/subscribe 完成后做一些事情。我正在 subscribe( onNext ) 方法中更改 Input 属性,但 ngOnChanges 永远不会触发。

我应该做些什么不同的事情?

import { Component, EventEmitter, 
  OnInit, AfterViewInit, OnChanges, SimpleChanges,
  Input, Output
} from '@angular/core';

@Component({
  templateUrl: 'myTemplate.html'
    , providers: [ NamesService ]
})

export class MyPage  {
  @Input() names: any[];

  constructor( public namesSvc: NamesService) {}

  ngOnInit() {
    this.getNames$()
  }


  getNames$() : void {
    this.nameService.get().subscribe( 
      (result)=>{
       this.names = result;
       console.log(`getNames$, names=${this.names}`);

       // I could doSomething() here, but it doesn't seem like the correct place
       // doSomething()  

      }
      , error =>  this.errorMessage = <any>error
    )
  }

  ngOnChanges(changes: SimpleChanges) : void {
    // changes.prop contains the old and the new value...
    console.warn(`>>> ngOnChanges triggered`)
    if (changes["names"]) {
      console.warn(`>>> ngOnChanges, names=${changes["names"]}`)
      this.doSomething()
    }
  }

  doSomething(){
    console.log("doing something");
  }
}

那是"as designed"

ngOnChanges() 仅在更改检测更新绑定到 @Input() 时调用。如果从某处强制更改输入,则不会调用它。

只需将 names 设为 getter/setter,以便每次更新 属性 时执行代码。

正如 Günter 所说,根据我的理解,它并不像那样工作...使用 Observables 时,您可以使用 Observable.next() 功能手动触发更改。这里的技巧是您必须从您的服务中 return 一个 Observable - 这可以像这样完成:

import {Observable, Subject} from "rxjs/Rx"; // remember the '/Rx', it got me...

export class NamesService {
    private initialNames: Array<string> = ["Joe", "Jack", "Pete"];

    get(){
        let names: Subject<Array<string>> = new Subject<Array<string>>();

        names.next(this.initialNames);
        setTimeout(() => {
            this.initialNames.push('someOtherNames');
            names.next(this.initialNames);
        }, 1000);
        return names.asObservable();
    }
}

然后像您已经完成的那样订阅它,当 .next() 运行时它将触发 .subscribe() 方法的更改。

不过,我建议将其与 get 方法分开,您可以拥有自己的 onNameUpdate() 方法,return 可观察数组或类似的方法。