【发布时间】:2019-03-10 05:43:45
【问题描述】:
我在Angular 6中创建了一个自定义轮播组件。简单的用法是这样的:
<mpx-carousel>
<div *mpxCarouselItem>Slide 1</div>
<div *mpxCarouselItem>Slide 2</div>
<div *mpxCarouselItem>Slide 3</div>
</mpx-carousel>
但它也支持嵌套,像这样:
<mpx-carousel>
<div *mpxCarouselItem>Slide 1</div>
<div *mpxCarouselItem>
<mpx-carousel>
<div *mpxCarouselItem>Sub-slide A</div>
<div *mpxCarouselItem>Sub-slide B</div>
</mpx-carousel>
</div>
<div *mpxCarouselItem>Slide 3</div>
</mpx-carousel>
在父CarouselComponent 代码中,我想确定是否有任何子CarouselComponents,并访问它们的属性。所以我使用@ContentChildren:
@ContentChildren(CarouselComponent, { descendants: true })
childCarousels: QueryList<CarouselComponent>;
ngAfterContentInit() {
console.log(this.childCarousels.length); // 1, BUT it's a reference to itself, not the child
}
在父轮播的 ngAfterContentInit 中,我看到 @ContentChildren 找到了 1 个子 CarouselComponent,这看起来不错。但仔细检查发现它实际上找到了这个父轮播本身,而不是它的子轮播。为了真正找到子轮播,我必须订阅 childCarousel.changes:
@ContentChildren(CarouselComponent, { descendants: true })
childCarousels: QueryList<CarouselComponent>;
ngAfterContentInit() {
console.log(this.childCarousels.length); // 1, BUT it's a reference to itself, not the child
this.childCarousels.changes.subscribe(() => {
console.log(this.childCarousels.length); // 2, now it includes itself and its child
});
}
所以@ContentChildren 包含父级本身有点奇怪,而且在检测到子级之前必须等待changes 事件有点奇怪,但这是一个足够简单的解决方法。
当子轮播在另一个组件中发现时,真正的麻烦就开始了。 CarouselComponent 是项目中很多其他组件使用的共享组件,所以我可以经常这样使用它...
<!-- parent carousel -->
<mpx-carousel>
<mpx-component-A></mpx-component-A>
<mpx-component-B></mpx-component-B>
</mpx-carousel>
...<mpx-component-A> 是另一个在内部使用自己的 mpx-carousel 的组件。我仍然希望这里的父轮播能够检测到 mpx-component-A 视图内使用的轮播。但是当我使用上述技术时,@ContentChildren 找不到在 ComponentA 中定义的 CarouselComponent 实例。在 ngAfterContentInit 中 childCarousels 只包含一个项目,它是对父级本身的引用。在这种情况下,childCarousels.changes 甚至从未触发过,所以我们也不会在那里找到埋藏的子轮播:
@ContentChildren(CarouselComponent, { descendants: true })
childCarousels: QueryList<CarouselComponent>;
ngAfterContentInit() {
console.log(this.childCarousels.length); // 1, BUT it's a reference to itself, not the child
// The changes event never even fires
this.childCarousels.changes.subscribe(() => {
console.log(this.childCarousels.length); // N/A
});
}
如果有帮助,我可以提供CarouselComponent 和CarouselItemDirective 的完整代码。但我的问题更笼统:父组件有没有办法获得对包含在另一个组件(ComponentA)内的特定类型(CarouselComponent)的后代组件的引用?
使用@ContentChildren 可能我完全找错了树,所以我对完全不同的方法持开放态度。
提前致谢!
编辑:
Here is a StackBlitz 这让我更清楚我想要做什么。请注意carousel.component.ts 中的 console.log() 语句和显示预期输出与实际输出的 cmets。 (注意:在现实世界中,轮播会每隔几秒就旋转一次它的项目。但为了简单起见,我在这里删除了所有这些)。
【问题讨论】:
标签: angular