简体   繁体   English

Angular ViewChildren 不会立即看到 ngFor 中的所有孩子

[英]Angular ViewChildren does not see all children from ngFor immediately

I have a strange behaviour of @ViewChildren corresponding to children components generated by ngFor.我有一个奇怪的@ViewChildren 行为,对应于 ngFor 生成的子组件。 @ViewChildren query does not see element standing in array for a quite long time. @ViewChildren 查询在很长一段时间内都看不到数组中的元素。 All my code is in the Plunker - see with console opened.我的所有代码都在Plunker 中- 打开控制台查看。

This is my main component:这是我的主要组成部分:

@Component({
    selector: 'my-app',
    template: `
        <button (click)="addInternalComponent()">Add internal component</button>
        <app-internal #internals *ngFor="let i of indexes" [index]="i
(afterViewInit)="onAfterViewInit()"></app-internal>
    `,
})
export class App {
    @ViewChildren('internals') internals: QueryList<InternalComponent>;
    indexes = [];
    addInternalComponent() {
        console.log('adding internal component!');
        this.indexes.push(this.indexes.length);
        console.log('Not complete list', this.internals._results);

    }

    onAfterViewInit() {
        console.log('onAfterViewInit - still not complete list', this.internals._results);
    }
}

Which has come children components that we can add by clicking a button.其中有我们可以通过单击按钮添加的子组件。

After adding an element into indexes array that generates all children in ngFor loop - we don't have that one that we just have added.在将元素添加到在 ngFor 循环中生成所有子项的索引数组中之后 - 我们没有刚刚添加的那个。

I can understand that behaviour - because maybe child component needs some time to create it and engine decides to console log before creating full child component.我可以理解这种行为 - 因为也许子组件需要一些时间来创建它并且引擎决定在创建完整的子组件之前控制台日志。

However I created emitter in child component signaling that both child's view and model are initialised.但是,我在子组件中创建了发射器,表明子组件的视图和模型都已初始化。 But... Handling this event in parent component - we still somehow doesn't have this item.但是......在父组件中处理这个事件 - 我们仍然没有这个项目。 How even is this possible?这怎么可能?

Child component:子组件:

export class InternalComponent implements AfterViewInit {
  @Input()
  index;
  @Output()
  afterViewInit: EventEmitter<any> = new EventEmitter<any>();

  ngAfterViewInit() {
    this.afterViewInit.emit();
  }

}

The standard way to be notified that the content of a QueryList has changed is to subscribe to its changes event in ngAfterViewInit :通知QueryList的内容已更改的标准方法是在ngAfterViewInit订阅其changes事件:

@ViewChildren("internals") internals: QueryList<InternalComponent>;

ngAfterViewInit() {
  this.internals.changes.subscribe((list: QueryList<InternalComponent>) => {
    // The updated QueryList is available here (with list or with this.internals)
    this.doSomethingWithInternals(list);
    this.doSomethingWithNewInternal(list.last);
    ...
  });
}

The event handling above may be all you need.上面的事件处理可能就是你所需要的。 If you still want to implement the afterViewInit event in InternalComponent , you can pass a reference to the component as a parameter of the event:如果你还想在InternalComponent实现afterViewInit事件,你可以传递一个对组件的引用作为事件的参数:

export class InternalComponent implements AfterViewInit {
  @Output() afterViewInit = new EventEmitter<InternalComponent>();

  ngAfterViewInit() {
    this.afterViewInit.emit(this);
  }

}

and retrieve the component in the event handler:并在事件处理程序中检索组件:

(afterViewInit)="onAfterViewInit($event)"

onAfterViewInit(component: InternalComponent) {
    this.useNewInternalComponent(component);
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM