在使用angular进行开发的时候,通过属性绑定向组件内部传值的方式,有时候并不能完全满足需求,比如我们写了一个公共组件,但是某个模板使用这个公共组件的时候,需要在其内部添加一些标签内容,这种情况下,除了使用ngIf
/ngSwitch
预先在组件内部定义之外,就可以利用ngTemplateOutlet
指令向组件传入内容.
ngTemplateOutlet
指令类似于angularjs中的ng-transclude
,vuejs中的slot
.
ngTemplateOutlet
是结构型指令,需要绑定一个TemplateRef
类型的实例.
使用方式如下:
@Component({
selector: 'app',
template: `
<h1>Angular's template outlet and lifecycle example</h1>
<app-content [templateRef]="nestedComponentRef"></app-content>
<ng-template #nestedComponentRef let-name>
<span>Hello {{name}}!</span>
<app-nested-component></app-nested-component>
</ng-template>
`,
})
export class App {}
@Component({
selector: 'app-content',
template: `
<button (click)="display = !display">Toggle content</button>
<template
*ngIf="display"
*ngTemplateOutlet="templateRef context: myContext">
</template>
`,
})
export class Content {
display = false;
@Input() templateRef: TemplateRef;
myContext = {$implicit: 'World', localSk: 'Svet'};
}
@Component({
selector: 'app-nested-component',
template: `
<b>Hello World!</b>
`,
})
export class NestedComponent implements OnDestroy, OnInit {
ngOnInit() {
alert('app-nested-component initialized!');
}
ngOnDestroy() {
alert('app-nested-component destroyed!');
}
}
代码中除了根组件外定义了两个组件
- 容器组件:
app-content
- 传递进去的内容组件:
app-nested-component
app-content
组件接收一个TemplateRef
类型的输入属性templateRef
,并在模板中将其绑定到了ngTemplateOutlet
指令,当组件接收到templateRef
属性时,就会将其渲染到ngTemplateOutlet
指令所在的位置.
上例中,app-content
组件templateRef
属性的来源,是在根组件的模板内,直接通过#
符号获取到了app-nested-component
组件所在<ng-template>
的引用并传入的.
在实际应用中,除了这种方式,也可以直接在组件内部获取TemplateRef
类型的属性并绑定到ngTemplateOutlet
指令.
比如在容器组件为模态框的情况下,并不能通过模板传值,就可以使用下面这种方式:
@ViewChild('temp') temp: TemplateRef<any>
openDialog(){
this.dialog.open(ViewDialogComponent, {data: this.temp)
}
在容器组件中还可以定义被传递内容的上下文(上例app-content
组件中的myContext
属性),其中的$implicit
属性作为默认值,在被传递的内容中可以以重命名的方式访问(上例let-name
),对于上下文中其他的属性,就需要通过let-属性名
的方式访问了.