我在 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
and CarouselItemDirective
如果有帮助的话。但我的问题更普遍:有没有办法让父组件获取对包含的某种类型(轮播组件)的后代组件的引用within另一个组件(ComponentS)?
我使用@ContentChildren可能完全搞错了树,所以我愿意接受完全不同的方法。
提前致谢!
EDIT:
这是一个 StackBlitz https://stackblitz.com/edit/angular-omiku4这让我更清楚我想要做什么。注意console.log()语句carousel.component.ts
以及显示预期输出与实际输出的评论。 (注意:在现实世界中,旋转木马每隔几秒就会以动画方式旋转其项目。但为了简单起见,我在这里删除了所有这些)。