关于ng-content /内容投影可能是一个奇怪的问题。我的想法是,您可以动态地放入“内容”,然后可以使用ng-content对其进行投影。我还可以做的一件事是使Input属性传递要在组件中显示的信息。
我遇到过这个项目; https://trimox.github.io/angular-mdc-web/#/home 这是Angular的新材料组件。我在浏览代码时发现的一件事是,他极大地利用了ng-content来投影某些“子组件”。我不禁奇怪...为什么?因为我也可以尝试使用一个卡组件和我传递的JSON /对象之类的配置来解决此问题。
<mdc-card class="demo-card">
<mdc-card-primary-action mdc-ripple>
<mdc-card-media class="demo-card__media--16-9" [wide]="true"></mdc-card-media>
<div class="demo-card__primary">
<h2 class="demo-card__title" mdcHeadline6>Our Changing Planet</h2>
<h3 class="demo-card__subtitle" mdcSubtitle2>by Kurt Wagner</h3>
</div>
<div class="demo-card__secondary" mdcBody2>
Visit ten places on our planet that are undergoing the biggest changes today.
</div>
</mdc-card-primary-action>
<mdc-card-actions>
<mdc-card-action-buttons>
<button mdc-button mdcCardAction="button">Read</button>
<button mdc-button mdcCardAction="button">Bookmark</button>
</mdc-card-action-buttons>
<mdc-card-action-icons>
<button mdcIconButton mdcCardAction="icon" iconOn="favorite" iconOff="favorite_border"></button>
<mdc-icon mdcCardAction="icon" mdcRipple>share</mdc-icon>
<mdc-icon mdcCardAction="icon" mdcRipple>more_vert</mdc-icon>
</mdc-card-action-icons>
</mdc-card-actions>
在上面,您可以看到例如带有多个项目的“卡片”组件。我也找到了这些组件的来源。 https://github.com/trimox/angular-mdc-web/blob/master/packages/card/card.ts。
我原来的问题仍然存在;什么时候使用ng-content是一个好习惯,什么时候不使用。为什么这是个好习惯?我还看到了DevExpress在他们的devextreme库中使用它; https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RecordGrouping/Angular/Light/
谢谢
答案 0 :(得分:2)
想象一下,如果您正在将数据从父级传递给子级。通常,我们将使用Input属性绑定,并在子ts中获取数据,然后将数据绑定。除了执行ng-content之外,我们还可以将内容放置在父级的component标签内并绑定父级数据,并在子级内使用ng-content,从而避免输入属性绑定
父组件
<parent>
<child>
<div class="head">{{heading}}</div>
</child>
</parent>
子组件
<ng-content select=".head"></ng-content>
在这里,我们直接绑定父数据,而不是使用输入属性绑定来处理数据
答案 1 :(得分:1)
让我简化您的问题。假设您要创建一个card
组件。您可以编写自己的子组件(连同执行必要的内容投影的代码),如下所示:
<card>
<card-title>My Title</card-title>
<card-content>
<p>Content here...</p>
<card-action>Some button here</card-action>
</card-content>
<card-footer>My footer</card-footer>
</card>
...或者您可以只创建一个<card>
组件并将其放入这样的配置对象中:
config = {
title: "My title",
content: {
innerHTML: "<p>Content here...</p>",
actions: [ {type: "button", text: "Some button here", onClick: "myFunction()"} ]
},
footer: "My footer"
}
那为什么要选择第一个选项?
1。语义HTML
一个原因是,通常,将结构(HTML),表示形式(CSS)和行为(JS / TS)分开是一种好习惯。由于card
组件可能包含其他结构元素,例如其标题,内容,动作,页脚等,因此最好用HTML表示此结构,而不要通过JavaScript / TypeScript来实现。您应该让您的HTML标记传达您内容的基本含义。这样做可以使您的代码更具语义性,简洁性,可维护性和可读性。也许如果您只是自己开发应用程序(而不是团队工作),那么由于您了解自己的代码,因此无需使其对他人具有语义/可读性。但是,您仍然应该使其对自己的将来可读,因为如果您希望在一年后查看代码,则可能希望代码具有语义性并且易于阅读。
2。利用Angular的模板synatx
选择第一个选项(使用内容投影和子组件)的另一个原因是,您可以在HTML中利用Angular的强大功能,例如数据绑定和*ngFor
。例如,如果要显示卡片列表,每张卡片都显示一个社交媒体帖子(例如在Facebook中),则可以轻松编写:
<card *ngFor="let post of posts">
<card-title>{{post.title}}</card-title>
<card-content>
<p>{{post.content}}</p>
<card-action>
<card-button (click)="likePost(post)">Like</card-button>
<card-button (click)="sharePost(post)">Share</card-button>
</card-action>
</card-content>
<card-footer>{{post.footer}}</card-footer>
</card>
而使用JS / TS配置对象来实现同一件事可能会更加困难。