TemplateRef
用于获取 <ng-template>
元素
用法一:在组件中使用自定义模板
如上: header 和 footer 需要使用自定义模板
// app.component.ts
import { Component, ElementRef, TemplateRef, ViewChild, ViewContainerRef, ViewRef } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<h1>TemplateRef</h1>
<app-detail [header]="header" [footer]="footer"></app-detail>
<ng-template #header>This is header template</ng-template>
<ng-template #footer>This is footer template</ng-template>
`
})
export class AppComponent {
title = 'demo-angular-material';
@ViewChild('header', { static: true }) headerTemplate: TemplateRef<any>;
@ViewChild('footer', { static: true }) footerTemplate: TemplateRef<any>;
constructor() {}
ngOnInit(): void {}
}
// detail.component.ts
import { Component, Input, OnInit, TemplateRef } from '@angular/core';
@Component({
selector: 'app-detail',
template: `
<ng-container *ngTemplateOutlet="header"></ng-container>
<div>详情明细...</div>
<ng-container *ngTemplateOutlet="footer"></ng-container>
`
})
export class DetailComponent implements OnInit {
@Input() header: TemplateRef<any>;
@Input() footer: TemplateRef<any>;
constructor() { }
ngOnInit() {}
}
ElementRef
相当于document.querySelector('XX')
, 主要用于获取 dom 元素
用法一:获取指定dom
@Component({
selector: 'app-root',
template: `
<h1>ElementRef</h1>
<div #content>主要内容...</div>
`
})
export class AppComponent {
title = 'demo-angular-material';
@ViewChild('content', { static: true }) content: ElementRef<any>;
constructor() {}
ngOnInit(): void {
console.log(this.content, this.content.nativeElement)
}
}
用法二:获取组件 / 指令的整个dom
通过在 构造函数 中注入的方式可以获得整个组件的dom
@Component({
selector: 'app-root',
template: `
<h1>ElementRef</h1>
<div #content>主要内容...</div>
`
})
export class AppComponent {
title = 'demo-angular-material';
constructor(private elementRef: ElementRef) {}
ngOnInit(): void {
console.log(this.elementRef, this.elementRef.nativeElement)
}
}
ViewContainerRef
视图容器,包含创建和操作 angular 视图的相关api ( 获取 <ng-container></ng-container>
)
angular中有两种视图类型:
- 插入式视图 Embedded Views
- 嵌入式视图的引用 EmbeddedViewRef
- *ngTemplateOutlet
- 宿主视图 component instance views,即组件实例视图
- 组件实例视图 引用 ComponentRef
- *ngComponentOutlet
ViewContainerRef中提供了两个创建上述两种视图的方法
abstract createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, options?: {
index?: number;
injector?: Injector;
}): EmbeddedViewRef<C>;
abstract createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C>;
创建内嵌视图
import { Component, ElementRef, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<h1>ElementRef</h1>
<div #content>主要内容...</div>
<ng-template #tpl>
<span>I am span in template</span>
</ng-template>
<ng-container #viewContainer></ng-container>
`
})
export class AppComponent {
@ViewChild('tpl', {static: true}) tpl: TemplateRef<any>;
@ViewChild('viewContainer', {read: ViewContainerRef}) viewContainer: ViewContainerRef;
constructor() {}
ngAfterViewInit(): void {
const embeddedRef = this.tpl.createEmbeddedView(null)
this.viewContainer.insert(embeddedRef)
console.log(this.tpl)
}
}
创建组件实例视图
import { Component, ComponentFactoryResolver, ElementRef, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
import { DetailComponent } from './detail/detail.component';
@Component({
selector: 'app-root',
template: `
<ng-container #test></ng-container>
`
})
export class AppComponent {
@ViewChild('test', {read: ViewContainerRef}) viewContainer: ViewContainerRef;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
ngAfterViewInit(): void {
const detailComponent = this.componentFactoryResolver.resolveComponentFactory(DetailComponent);
this.viewContainer.clear()
this.viewContainer.createComponent(detailComponent);
}
}