gpt4 book ai didi

angular - 结合使用 @ViewChildren/@ContentChildren 和 router-outlet

转载 作者:太空狗 更新时间:2023-10-29 18:17:34 30 4
gpt4 key购买 nike

我正在尝试构建这个:

┌--------------------------------------------┐
| -Page 1- -Page 2- -Page 3- |
├----------┬---------------------------------┤
| Link 1 | <router-outlet></router-outlet> |
| Link 2 | |
| Link 3 | |
| | |
| | |

左侧的链接列表取决于页面。

一个典型的页面是这样的:

<div>
<app-component-1 appAnchor anchorTitle="Link 1"></app-component-1>
<app-component-2 appAnchor anchorTitle="Link 2"></app-component-2>
<app-component-3 appAnchor anchorTitle="Link 3"></app-component-3>
</div>

有一些指令 appAnchor 关联到 @Input() anchorTitle: string 。我想自动捕获它们并更新左侧菜单。

当我尝试通过 router-outlet 查询这些元素时,问题就来了。

所以我尝试了:

@ViewChildren(AnchorDirective)
viewChildren: QueryList<AnchorDirective>;

@ContentChildren(AnchorDirective)
contentChildren: QueryList<AnchorDirective>;

ngAfterContentInit(): void {
console.log(`AppComponent[l.81] contentChildren`, this.contentChildren);
}

ngAfterViewInit(): void {
console.log(`AppComponent[l.85] viewChildren`, this.viewChildren);
}

但我总是得到一些空的 QueryList :

QueryList {dirty: false, _results: Array(0), changes: EventEmitter, length: 0, last: undefined, …}

我也试过:

@ContentChildren(AnchorDirective, {descendants: true})
@ContentChildren(AnchorDirective, {descendants: false})

最后,我尝试在最后一刻查询元素:

<router-outlet (activate)="foo()"></router-outlet>

注意:我不希望子组件通过服务向父组件发送数据,因为它会导致一些 ExpressionChangedAfterItHasBeenCheckedErroris considered as a bad practice .我真的更愿意直接从父组件查询链接。

编辑:这是一个stackBlitz显示问题。如果在组件内部使用了 @ViewChildren,则一切正常。但是,如果从根组件使用 @ViewChildren,则会失败。

最佳答案

正在进行讨论 here关于 ContentChildren 的工作原理,它与您的问题密切相关。

并且在 this comment据解释:

In Angular content projection and queries it means "content as it was written in a template" and not "content as visible in the DOM"

The consequence of this mental model is that Angular only looks at the nodes that are children in a template (and not children in the rendered DOM).

与上述问题类似,通过 router-outlet 激活的组件不被视为 ViewChildrenContentChildren。它们只是 DOM 子级,这并不意味着在 View 和内容查询方面有任何 Angular 。没有办法(截至今天)使用 ViewChildViewChildrenContentChildContentChildren 查询它们

我的建议是结合使用 activate 事件和 RouterOutletcomponent 属性来解决您的问题。以实现所需的行为。因此:

定义router-outlet如下:

<router-outlet #myRouterOutlet="outlet" (activate)='onActivate()'></router-outlet>

并按如下方式使用它:

@ViewChild("myRouterOutlet", { static: true }) routerOutlet: RouterOutlet;
nbViewChildren: number;
links = [];

onActivate(): void {
setTimeout(() => {
const ancList: QueryList<AnchorDirective> = (this.routerOutlet.component as any).children;

this.nbViewChildren = ancList.length;
this.links = ancList.map(anc => anc.anchorTitle);
})
}

这是一个改进了打字的工作演示:https://stackblitz.com/edit/angular-lopyp1

另请注意,setTimeout 是必需的,因为 onActivate 在组件生命周期尚未开始或完成的路由期间被触发。 setTimeout 确保组件生命周期已完成,并且组件和底层查询也已准备就绪。

关于angular - 结合使用 @ViewChildren/@ContentChildren 和 router-outlet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56955317/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com