当使用ContentChildren
和async
管道时,可能会遇到返回空数组的情况。这是因为在Angular的变更检测机制中,ContentChildren
查询是在父组件的ngAfterViewInit
钩子之前进行的,而async
管道是在ngAfterViewInit
钩子之后进行的。因此,当async
管道尝试订阅ContentChildren
查询的结果时,查询还没有完成,因此返回的是空数组。
为了解决这个问题,我们可以使用ngAfterContentChecked
生命周期钩子来替代ngAfterViewInit
,以确保ContentChildren
查询在async
管道订阅之前完成。下面是一个示例代码:
import { Component, ContentChildren, QueryList, AfterContentChecked } from '@angular/core';
import { Observable } from 'rxjs';
@Component({
selector: 'app-parent',
template: `
{{item}}
`,
})
export class ParentComponent implements AfterContentChecked {
@ContentChildren(ChildComponent) children: QueryList;
items$: Observable;
ngAfterContentChecked() {
// 使用ngAfterContentChecked确保ContentChildren查询在async管道订阅之前完成
this.items$ = this.children.changes.pipe(
startWith(null),
map(() => this.children.toArray().map(child => child.value))
);
}
}
@Component({
selector: 'app-child',
template: '',
})
export class ChildComponent {
value: number;
}
在上述示例中,我们将ngAfterViewInit
钩子改为ngAfterContentChecked
钩子,并将ContentChildren
查询移动到了这个钩子中。同时,我们使用changes
属性来订阅QueryList
的变化,并使用startWith(null)
确保第一次订阅时也会执行查询。然后,我们使用map
操作符将QueryList
转换为一个包含子组件值的Observable。
这样,我们就可以确保在使用async
管道时,ContentChildren
查询会在查询结果订阅之前完成,从而避免返回空数组的问题。