一样这一篇最要讲概念而已.
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 很难写)