Angular 2:ngSwitch或ViewContainerRef.createComponent

时间:2016-11-24 20:54:27

标签: angular

我有一个案例,我在列表中动态创建组件(刷新很多)并使用ngSwitch这样:

<div *ngFor='let item of items'>
   <div [ngSwitch]="item.view">
        <view-one *ngSwitchCase="'one'"></view-one>
        <view-two *ngSwitchCase="'two'"></view-two>
        <view-three *ngSwitchCase="'three'"></view-three>
    </div>
</div>

我想知道是否有更好的更有效的方法,或者这是正确的方法吗?

我已经看到人们动态创建组件,但是api已经改变了很多次,很难知道什么是正确的。看来ViewContainerRef.createComponent()可能是替代方案吗?

2 个答案:

答案 0 :(得分:5)

我更喜欢... AtomicInteger pos = new AtomicInteger(0); AtomicInteger split = new AtomicInteger(batchLength); Map<Integer, List<Integer>> map = integerList.stream() .collect(Collectors.groupingBy(e -> Integer.valueOf(pos.getAndIncrement() / split.get()))); 而不是createComponent(),因为我认为它更容易测试和扩展。我还没有看到任何表现不足。

这是我目前方法的简化形式:

ngSwitch

现在您可以通过以下方式使用它:

@Component({
    selector: "my-item",
    template: `
        <div #placeholder></div>
    `
})
export class MyItemComponent implements AfterViewInit {
    @Input() item: any;
    @ViewChild("placeholder", {read: ViewContainerRef}) placeholderRef: ViewContainerRef;

    constructor(
        private componentFactoryResolver: ComponentFactoryResolver) {
    }

    ngAfterViewInit() {
        switch(this.item.view) {
            case "one":
                this.loadItem(OneItemComponent);
            case "two":
                this.loadItem(TwoItemComponent);
            default:
                throw new Error("Unknown item!");
        }
    }

    private loadItem(component: Type<any>) {
        const factory = this.componentFactoryResolver.resolveComponentFactory(component);
        const componentRef = this.placeholderRef.createComponent(factory);
        componentRef.instance.item = this.item;
        componentRef.changeDetectorRef.detectChanges();
    }
}

答案 1 :(得分:2)

以下是我在应用中实施动态组件的方法:

export class DynamicComponent implements AfterViewInit, OnChanges, OnDestroy {
    @Input() model: any;
    @Input() factory: ComponentFactory<any>;
    @ViewChild('target', { read: ViewContainerRef }) target: any;

    private initialized: boolean = false;
    private componentRef: ComponentRef<any>;

    private updateComponent() {
        if (!this.initialized || !this.factory) {
            return;
        }

        if (this.componentRef) {
            this.componentRef.destroy();
        }

        this.componentRef = this.target.createComponent(this.factory);
        this.componentRef.instance.model = this.model;
        this.componentRef.changeDetectorRef.detectChanges();
    }

    ngOnChanges() {
        this.updateComponent();
    }

    ngAfterViewInit() {
        this.initialized = true;
        this.updateComponent();
    }

    ngOnDestroy() {
        if (this.componentRef) {
            this.componentRef.destroy();
        }
    }
}

要使其工作,您需要一个包含

的模板
<div #target><div>

对于这个类,它将出现动态创建的组件。

以下是它的使用方式:

<dynamic [factory]="myFactory" [model]="myModel"></dynamic>

myFactoryComponentFactory,例如

let factory = this.resolver.resolveComponentFactory(MyComponent);

其中resolverComponentFactoryResolver(来自@angular/core)。

myModel是您可以传递给新创建的组件的数据,并且可以作为@Input()参数使用。