【发布时间】:2017-09-21 08:15:28
【问题描述】:
我对@987654321@ 和createComponent 的用例感到困惑,即何时使用哪一个。
请提出一些案例,说明在“动态创建场景”中使用它们的合适设置。
【问题讨论】:
标签: angular
我对@987654321@ 和createComponent 的用例感到困惑,即何时使用哪一个。
请提出一些案例,说明在“动态创建场景”中使用它们的合适设置。
【问题讨论】:
标签: angular
请参阅this workshop on DOM manipulation 或阅读Working with DOM in Angular: unexpected consequences and optimization techniques,我会通过示例解释差异。
这两种方法都用于向组件视图 (DOM) 动态添加内容。此内容可以是模板或基于组件。在 Angular 中,我们通常使用ViewContainerRef 来操作 DOM。并且这两种方法都可以使用:
class ViewContainerRef {
...
createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C>
createComponent<C>(componentFactory: ComponentFactory<C>, index?: number, injector?: Injector, projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>
}
要了解有关操作 DOM 的更多信息,请阅读 Exploring Angular DOM manipulation techniques using ViewContainerRef。
它用于使用TemplateRef 创建视图。 TemplateRef 由 Angular 编译器在组件 html 中遇到 ng-template 标签时创建。
使用此方法创建的视图称为embedded view。
import { VERSION, Component, ViewChild, TemplateRef, ViewContainerRef } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<ng-container #vc></ng-container>
<ng-template #tpl>
<h1>Hello, {{name}}</h1>
</ng-template>
`,
styles: ['']
})
export class AppComponent {
name = `Angular! v${VERSION.full}`;
@ViewChild('tpl', {read: TemplateRef}) tpl: TemplateRef<any>;
@ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;
ngOnInit() {
this.vc.createEmbeddedView(this.tpl);
}
}
*ngIf 和 *ngFor 等所有结构指令都使用这种方法,因为它们都是包装 ng-template。例如,*ngIf 的代码:
<div *ngIf="data">{{name}}</div>
变成了
<ng-template ngIf="data">
<div>{{name}}</div>
而ngIf 指令在内部使用createEmbeddedView:
@Directive({selector: '[ngIf]'})
export class NgIf {
private _updateView() {
...
if (this._thenTemplateRef) {
this._thenViewRef =
this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);
它用于使用ComponentFactory 创建视图。当您在模块的bootstrap 属性中指定组件时,Angular 编译器会创建它,因此编译器会为其生成工厂。使用此方法创建的视图称为hostview。
import { Component, ViewContainerRef, ComponentFactoryResolver, NgZone, VERSION, ViewChild } from '@angular/core';
@Component({
selector: 'hello',
template: `<h1>Hello Component!</h1>`,
styles: [``]
})
export class HelloComponent {}
@Component({
selector: 'my-app',
template: `
<ng-container #vc></ng-container>
`,
styles: ['']
})
export class AppComponent {
@ViewChild('vc', {read:ViewContainerRef}) vc: ViewContainerRef;
constructor(private resolver: ComponentFactoryResolver) {}
ngOnInit() {
const factory = this.resolver.resolveComponentFactory(HelloComponent);
this.vc.createComponent(factory);
}
}
要详细了解主机视图和嵌入式视图之间的区别,请阅读What is the difference between a view, a host view and an embedded view
【讨论】:
ng-template 创建的,并且没有与它们相关联的类而不是组件,因此确实没有太多逻辑可以放在embedded view 中。但是,我会说大多数嵌入式视图用于可重用的演示文稿。所有结构指令都使用ng-template。我会在答案中添加一点