从 Angular 2 理解 *ngFor
Posted
技术标签:
【中文标题】从 Angular 2 理解 *ngFor【英文标题】:Understanding *ngFor from Angular 2 【发布时间】:2019-02-03 01:06:00 【问题描述】:我正在尝试在我的 Angular 项目中使用嵌套的 *ngFor 来呈现动态菜单。我正在尝试这样的事情:
<li class="treeview" *ngFor="let pm of parentMenu">
<a href="#">
<i class="fa fa-edit"></i> <span>pm.MenuTitle</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu" *ngFor="let cm of childMenu">
<li *ngIf="cm.ParentMenuId == pm.Id">cm.MenuTitle</li>
</ul>
</li>
我只得到 childMenu 的第一个元素,我的理解是 *ngFor 的工作类似于 C# 中的 foreach,但显然情况并非如此。有人可以帮我修复代码并理解它吗?
【问题讨论】:
*ngIf works similar to foreach
我猜你的意思是*ngFor
,它确实像forEach
一样工作。 *ngIf
像 if
一样工作(这里没有惊喜)
是的,抱歉,会更新问题。
内部 *ngFor 会生成几个 li 元素,但 *ngIf 只会挑选出一个。还是其中几个条件为真?
那么它是如何工作的,第一次从外循环迭代,然后从内循环进行所有迭代,然后从外循环进行第二次迭代,再从内循环进行所有迭代,等等?
是的,就像一个外部和一个内部 for 循环
【参考方案1】:
试试这个代码
<ul class="treeview-menu" *ngFor="let cm of pm.childMenu">
<li *ngIf="cm.ParentMenuId == pm.Id">cm.MenuTitle</li>
</ul>
【讨论】:
pm 没有 childMenu 属性。我正在读取两个不同的数组,parentMenu 和 childMenu。 为什么你有两个数组?【参考方案2】:您可以通过使用模板、容器或组件的递归调用来实现递归菜单。您可以采用不同的方法。
Angular2 Navigation Menu with Recursive Templates
Recursion in Angular Components
Angular *ngFor recursive list tree template
【讨论】:
【参考方案3】:我不知道您的 .ts
文件的内容,但您的代码在这里可以正常工作:
https://stackblitz.com/edit/angular-sduuwm
请注意,我已经像这样定义了我的数组:
parentMenu = [
Id: 1,
MenuTitle: "One",
,
Id: 2,
MenuTitle: "Two",
,
Id: 3,
MenuTitle: "Three",
];
childMenu = [
ParentMenuId: 1,
MenuTitle: "One quarter"
,
ParentMenuId: 1,
MenuTitle: "One half"
,
ParentMenuId: 2,
MenuTitle: "Two half"
,
ParentMenuId: 3,
MenuTitle: "Three half"
];
但是,也就是说,如果我是你,我宁愿这样定义我的数组:
parentMenu = [
Id: 1,
MenuTitle: "One",
childMenu: [
MenuTitle: "One quarter" ,
MenuTitle: "One half" ,
]
,
Id: 2,
MenuTitle: "Two",
childMenu: [
MenuTitle: "Two half" ,
]
,
Id: 3,
MenuTitle: "Three",
childMenu: [
MenuTitle: "Three half" ,
]
];
并像这样编写 html:
<a href="#">
<i class="fa fa-edit"></i> <span>pm.MenuTitle</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu" *ngFor="let cm of pm.childMenu">
<li>cm.MenuTitle</li>
</ul>
而且您的代码中不需要*ngIf
测试。
【讨论】:
对不起,我必须投反对票。如果你有父母,孩子有一个 uniq 对象。如果你有一个 uniq 对象,你必须使用 *ngFor="let child of pm .children" 无法理解您的评论,伙计,请更全面地证明您的反对意见。我同意替代解决方案不适用于他的 HTML,但它确实向他展示了解决问题的替代解决方案。 我最好不要使用 *ngIf 来只显示一个元素。您可以使用 let i=index 并显示 parentMenu[i].MenuTitle(仅使用最后一个 *ngFor)或仅将两个数组转换为一个。无论如何我只是删除了downvote(但我觉得答案不正确)【参考方案4】:<ul>
<ng-template #recursiveMenu let-parentMenu>
<li class="treeview" *ngFor="let pm of parentMenu">
<a href="#">
<i class="fa fa-edit"></i> <span>pm.MenuTitle</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<ng-container *ngTemplateOutlet="recursiveMenu; context:
$implicit: pm.childMenu">
</ng-container>
</ul>
</li>
</ng-template>
<ng-container *ngTemplateOutlet="recursiveMenu; context:
$implicit: parentMenu">
</ng-container>
</ul>
【讨论】:
能否给你的代码添加一点解释。【参考方案5】:你是正确的,ngFor 的行为类似于 foreach 或 for 循环。
我怀疑你的问题是你绑定的对象。
基本上使用您的代码,组件上应该有一个名为 parentItem 的属性,它是一个具有嵌套属性的数组,包括 childMenu
parentMenu =
'Parent1':['menuTitle':'Menu 1', 'childItem':[
'menuTitle':'sub item 1']
,
'menuTitle':'A cool menu', 'childItem':[
'menuTitle':'sub item 1',
'menuTitle': 'sub item 2']
]
然后你的 HTML 应该像这样工作:
<li class="treeview" *ngFor="let pm of parentMenu.Parent1">
<a href="#">
<i class="fa fa-edit"></i> <span>pm.menuTitle</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu" *ngFor="let cm of pm.childItem">
<li>cm.menuTitle</li>
</ul>
</li>
对于reference in action a working stackblitz from your code:
【讨论】:
即使根据您的建议重构了代码,我仍然只得到子菜单的第一个元素。渲染长度时,它显示 2 但只有第一个元素被渲染。我现在完全糊涂了。它应该可以工作。 我的 html 模板似乎有问题。在删除所有引导类并只放置纯 html 后,一切都正确呈现。 我不得不把内部 *ngFor 放在 而不是 中,如下所示: cm.MenuTitle以上是关于从 Angular 2 理解 *ngFor的主要内容,如果未能解决你的问题,请参考以下文章
ngAfterContentChecked() 无法理解 + 角度 2