ngIf容器中断异步ngFor



当我将ngIf容器包装在使用ngFor创建的列表中时,Angular2中出现了一些意外行为。在ngIf容器变为可见之后,第一次插入可观察数组中的项时,视图似乎不会呈现这些项。

请看演示这种意外行为的plunker演示。我预计第一个示例将在出现Loaded的同时显示香蕉

我是在做一些愚蠢的事情,还是这是一个渲染错误


Plunker演示

app.service.ts

export class AppService {
  private _things = new Subject<Array<any>>();
    public things = this._things.asObservable();
  constructor() {
    var that = this;
    // simulate ajax request
    setTimeout(function() {
      that._things.next([
          {'id': 1, 'text': 'banana'}
        ]);
    }, 3000);
    setTimeout(function() {
      that._things.next([
        {'id': 1, 'text': 'banana'},
        {'id': 2, 'text': 'orange'}
      ]);
    }, 6000);
    setTimeout(function() {
      that._things.next([
        {'id': 1, 'text': 'banana'},
        {'id': 2, 'text': 'orange'},
        {'id': 3, 'text': 'apple'}
      ]);
    }, 9000);
  }
}

app.ts

@Component({
  selector: 'my-app',
  template: `
    <h4>Does have *ngIf</h4>
    <div *ngIf="hasThings">
      Loaded
      <ul>
        <li *ngFor="let thing of things | async">
          {{thing.id}}: {{thing.text}}
        </li>
      </ul>
    </div>
    <h4>Doesn't have *ngIf</h4>
    <div>
      Loaded
      <ul>
        <li *ngFor="let thing of things | async">
          {{thing.id}}: {{thing.text}}
        </li>
      </ul>
    </div>
  `,
  directives: [NgClass, NgStyle, CORE_DIRECTIVES, FORM_DIRECTIVES]
})
export class App implements OnInit {
  public hasThings = false;
  private _things = new Subject<Array<any>>();
  public things = this._things.asObservable();
  constructor(private _appService: AppService) {
  }
  ngOnInit() {
    this._appService.things
      .subscribe(things => {
        this.hasThings = things.length > 0;
        this._things.next(things);
      });
  }
}

原因是您在组件中使用Subject,在模板中使用async管道。如果将Component中的Subject对象更改为BehaviorSubject,则会得到预期的结果。

private _things = new BehaviorSubject<Array<any>>();

SubjectBehaviorSubject之间的主要区别之一是,BehaviorSubject会在您订阅它时向您返回它保留的最后一个值,而Subject不会。在您的代码中,当满足第一个ngIf条件时,DOM将被启动,第一个列表将调用subscribe。届时,Subject将不会发出任何内容,您必须等到下一个事件更新列表。

工作地点:https://plnkr.co/edit/Obso0Odl3PoPw699AQ5W?p=preview

最新更新