首页 > 代码库 > angular2 学习笔记 ( Dynamic Component 动态组件)

angular2 学习笔记 ( Dynamic Component 动态组件)

一样这一篇最要讲概念而已.

 

refer :

http://blog.rangle.io/dynamically-creating-components-with-angular-2/ (例子)
https://www.ag-grid.com/ag-grid-angular-aot-dynamic-components/ (动态 entryComponents)

http://stackoverflow.com/questions/40106480/what-are-projectable-nodes-in-angular2 (Projectable nodes, something like transclude)

http://stackoverflow.com/questions/38888008/how-can-i-use-create-dynamic-template-to-compile-dynamic-component-with-angular ( dynamic Jit version )

https://medium.com/@isaacplmann/if-you-think-you-need-the-angular-2-runtime-jit-compiler-2ed4308f7515#.72ln3bcsy (many way Aot version)

http://stackoverflow.com/questions/39033835/angularjs2-preload-server-configuration-before-the-application-starts ( angular initialize )

 

动态组件分 2 种 

1. Jit

2. Aot

Jit 的情况下你可以动态的写组件模板, 最后 append 出去, 类似 ng1 的 $compile 

Aot 的话, 模板是固定的, 我们只是可以动态创建 component 然后 append 出去

这一篇只会谈及 Aot 

 

要知道的事项 : 

1. 所有要动态的组件都要另外声明到 entryComponents 里头, 原因是 ng 是通过扫描模板来 import component class 的, 动态组件不会出现在模板上所以我们要用另一个 way 告诉 ng。

2. 目前只有动态组件,没有动态指令

3. 例子 

@Component({
    selector: ‘aaa‘,
    template: ``
})
export class AAAComponent implements OnInit, AfterContentInit {
    constructor(
        private vcr: ViewContainerRef,
        private cfr: ComponentFactoryResolver
    ) { }

    @ContentChildren("dynamic", { read: ElementRef }) elem: QueryList<ElementRef>  //read 的作用是强转类型

    ngOnInit() {


    }

    ngAfterContentInit() {                   
        let providers = ReflectiveInjector.resolve([AbcService]); //为组件添加 providers
        let injector = ReflectiveInjector.fromResolvedProviders(providers, this.vcr.parentInjector); //创建注入器给 component (记得要继承哦)
        let factory = this.cfr.resolveComponentFactory(AbcComponent); //创建 component 工厂
        let component = factory.create(injector,[[this.elem.first.nativeElement],[this.elem.last.nativeElement] ]); //创建 component, 这是就把注入器放进了, 后面的 array 是给 ng-content 用的
        component.instance.name = "keatkeat"; // 对 input, output 做点东西 
        this.vcr.insert(component.hostView, 0); // 插入到模板中  0 是 position, 如果是 0 其实可以不用放. 

        // 如果不需要设定 providers 的话,可以省略一些 : 
        // let factory = this.resolver.resolveComponentFactory(AbcComponent);  
        // let component = this.vcr.createComponent(factory, 0);
        // component.instance.name = "keatkeat";   
    }
}

里头说的 ng-content, 就是 Projectable nodes , 我个人认为这个做法还不太理想,因为 ng-content 应该是可以通过 select 找到对应的 tranclude 的,不过这里的参数 array 已经固定了 tranclude 的位置. 

我的想法是, 如果你要做类似 tranclude 的事情, 改用 input 传递 templateRef. 

类似这样 

@Component({    
    template : `
        <p>final</p>
        <template [ngTemplateOutlet]="template" [ngOutletContext]="{ innerValue : ‘huhu‘ }" ></template>
    `,
    selector : "final"
})
export class FinalComponent implements OnInit {
    constructor(
    ) { }

    @Input()
    template : TemplateRef<any> //传进来

    ngOnInit() {       
        console.log(this.template);
    }
}

 4. 个人的想法 

一个动态组件应该和平时的组件是一样的,意思是我们可以随时把任何一个组件改成动态调用的方式. 

不过目前 ng 支持的不是很好

-input, output (这个可以)

-tranclude (Projectable nodes 显然和 ng-content配合不上)

-在 component 上方指令 (动态创建的 component, 没办法加上指令, 这导致了 dynamic accessor 很难写)

 

angular2 学习笔记 ( Dynamic Component 动态组件)