angular插槽总结
1、ng-content作用:内容投影,将组建内部写的组件或者html覆盖父组件的ng-content使用场景:编写组件中需要融入其他组件(类似vue slot)例:app-d3chart中需要加入app-new-small-card组件,app-new-small-card需要加入app-small-panel组件,只需要在app-d3chart中加<ng-conten...
-
1、ng-content
作用:内容投影,将组建内部写的组件或者html覆盖父组件的ng-content
使用场景:编写组件中需要融入其他组件(类似vue slot)
例:app-d3chart中需要加入app-new-small-card组件,app-new-small-card需要加入app-small-panel组件,只需要在app-d3chart中加<ng-content></ng-content>标签即可。
<app-d3chart [height]="633" [type]="'world'" [cardId]="'card_dashboard_map'"> <app-new-small-card [totalHeight]="600"> <app-small-panel #smallPanel [timeer]="timeer"></app-small-panel> </app-new-small-card> </app-d3chart>
ng-content有个select属性,可以做一些判断,满足条件再显示要填充的外部内容,支持 CSS 选择器(
my-element
,.my-class
,[my-attribute]
,...)来匹配你想要的内容。如果不设置就全部接受。例:
/*父组件*/ <app-parent> <app-child class="red"></app-child> <app-child name="child"></app-child> </app-parent> /*子组件 对号入座*/ <div style="background: cyan"> <ng-content select="[name=child]"></ng-content> </div> <div style="background: pink"> <ng-content select=".red"></ng-content> </div>
ng-content有
@ContentChild
装饰器,可以用来调用投影内容了,和@ViewChild
非常类似。异同点如下:相同点
- 都是属性装饰器
- 都有对应的复数形式装饰器:ContentChildren、ViewChildren
- 都支持 Type
不同点
- ContentChild 用来从通过 Content Projection 方式 (ng-content) 设置的视图中获取匹配的元素
- ViewChild 用来从模板视图中获取匹配的元素
- 在父组件的 ngAfterContentInit 生命周期钩子中才能成功获取通过 ContentChild 查询的元素
- 在父组件的 ngAfterViewInit 生命周期钩子中才能成功获取通过 ViewChild 查询的元素
-
2、ng-template
作用:用来渲染 HTML,它永远不会直接显示出来。 事实上,在渲染视图之前,Angular 会把
<ng-template>
及其内容替换为一个注释。一般和判断指令一起使用。符合条件才渲染。不会渲染
<ng-template> <div>Loading...</div> </ng-template>
会渲染
<div class="lessons-list" *ngIf="lessons else loading"> ... </div> <ng-template #loading> <div>Loading...</div> </ng-template>
使用场景:
1、模板引用,使用ViewChild 装饰器注入
例:defaultTabButtons这块可以
@Component({ selector: 'app-root', template: ` <ng-template #defaultTabButtons> <button class="tab-button" (click)="login()"> {{loginText}} </button> <button class="tab-button" (click)="signUp()"> {{signUpText}} </button> </ng-template> `}) export class AppComponent implements OnInit { @ViewChild('defaultTabButtons') private defaultTabButtonsTpl: TemplateRef<any>; ngOnInit() { console.log(this.defaultTabButtonsTpl); } }
2、通过 @Input 导入部分模板(组合模式),与其他模板组合在一起,以形成最终的组件模板。一般和ngTemplateOutlet(实例化模板)一起使用,用于动态填充或插入相应的内容。
例:如果父组件nzTitle配置的是字符串,就显示字符串内容,如果不是,通过ngTemplateOutlet指令动态去创建。
<ng-template #titleTemplate> <ng-template [ngTemplateOutlet]="nzTitle"></ng-template> </ng-template> <div class="ant-card-head" *ngIf="nzTitle||nzExtra||tab"> <div class="ant-card-head-wrapper"> <div class="ant-card-head-title" *ngIf="nzTitle"> <ng-container *ngIf="isTitleString; else titleTemplate">{{ nzTitle }}</ng-container> </div> </div> </div>
<nz-card [nzBordered]="false" [nzTitle]="titleRiskTrendTop10"> <ng-template #titleRiskTrendTop10> 风险趋势排行TOP10 </ng-template> <app-risk-trend-top10 #riskTrendTop10 [timeer]="timeer"></app-risk-trend-top10> </nz-card>
3、动态加载
例如广告条场景,先使用一个名叫
AdDirective
的辅助指令来在模板中标记出有效的插入点。import { Directive, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[ad-host]', }) export class AdDirective { constructor(public viewContainerRef: ViewContainerRef) { } }
加载到模块组件位置,选择器ad-host是AdDirective服务的,ad-host不用带尖括号。
template: ` <div class="ad-banner"> <h3>Advertisements</h3> <ng-template ad-host></ng-template> </div>
4、和结构型指令一起使用
例:下面俩种写法是一样的,星号是一个用来简化更复杂语法的“语法糖”。 从内部实现来说,Angular 把
*ngIf
属性 翻译成一个<ng-template>
元素 并用它来包裹宿主元素。
<div>
上的其余部分,包括它的class
属性在内,移到了内部的<ng-template>
元素上。<div *ngIf="hero" class="name">{{hero.name}}</div> <ng-template [ngIf]="hero"> <div class="name">{{hero.name}}</div> </ng-template>
5、结构型指令。
例:这个例子结构型指令会从 Angular 生成的
<ng-template>
元素中创建一个内嵌的视图,并把这个视图插入到一个视图容器中,紧挨着本指令原来的宿主元素<p>
(译注:注意不是子节点,而是兄弟节点)。你可以使用
TemplateRef
取得<ng-template>
的内容,并通过ViewContainerRef
来访问这个视图容器。你可以把它们都注入到指令的构造函数中,作为该类的私有属性。
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; /** * Add the template content to the DOM unless the condition is true. */ @Directive({ selector: '[appUnless]'}) export class UnlessDirective { private hasView = false; constructor( private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) { } @Input() set appUnless(condition: boolean) { if (!condition && !this.hasView) { this.viewContainer.createEmbeddedView(this.templateRef); this.hasView = true; } else if (condition && this.hasView) { this.viewContainer.clear(); this.hasView = false; } } } <p *appUnless="condition" class="unless a"> (A) This paragraph is displayed because the condition is false. </p> <p *appUnless="!condition" class="unless b"> (B) Although the condition is true, this paragraph is displayed because appUnless is set to false. </p>
-
3、ng-container
作用:是一个分组元素,把一些兄弟元素归为一组,但它不会污染样式或元素布局。因为 Angular 不会把它渲染到 DOM 中。
使用场景:字符串拼接时,需要满足条件才显示的部分,如果用其他标签包裹起来进行判断,可能会有样式问题。
例1:字符串拼接时,如果span标签有样式,就会导致这一行字体不一样
<p> I turned the corner <span *ngIf="hero"> and saw {{hero.name}}. I waved </span> and continued on my way. </p>
用ng-container就不会有这种顾虑
<p> I turned the corner <ng-container *ngIf="hero"> and saw {{hero.name}}. I waved </ng-container> and continued on my way. </p>
例2:select根据条件排除选择框中的某个
<option>
。浏览器不会显示<span>
中的<option>
。<div> Pick your favorite hero (<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>) </div> <select [(ngModel)]="hero"> <span *ngFor="let h of heroes"> <span *ngIf="showSad || h.emotion !== 'sad'"> <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option> </span> </span> </select>
使用ng-container可正常显示
<div> Pick your favorite hero (<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>) </div> <select [(ngModel)]="hero"> <ng-container *ngFor="let h of heroes"> <ng-container *ngIf="showSad || h.emotion !== 'sad'"> <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option> </ng-container> </ng-container> </select>
更多推荐
所有评论(0)