angular 学习笔记 ( Dynamic Component 动态组件)
2018-01-26 10:32
519 查看
动态组件分 2 种
1. Jit
2. Aot
Jit 的情况下你可以动态的写组件模板, 最后 append 出去, 类似 ng1 的 $compile
Aot 的话, 模板是固定的, 我们只是可以动态创建 component 然后 append 出去
这一篇只会谈及 Aot
要知道的事项 :
1. 所有要动态的组件除了需要 declarations之外还要声明到 entryComponents 里头, 原因是 ng 是通过扫描模板来 import component class 的, 动态组件不会出现在模板上所以我们要用另一个 way 告诉 ng。
要方便扩展的话可以用 provides, ng-router 也是用这个实现的.
2. 目前只有动态组件,没有动态指令 (呃..所以动态创建的组件就不能附带指令咯.../.\)
3. 例子
里头说的 ng-content, 就是 Projectable nodes , 我个人认为这个做法还不太理想,因为 ng-content 应该是可以通过 select 找到对应的 tranclude 的,不过这里的参数 array 已经固定了 tranclude 的位置.
所以目前, 如果你要做类似 tranclude 的事情, 改用 input 传递 templateRef 反而会比较容易控制.
类似这样
4. 个人的想法
一个动态组件应该和平时的组件必须是一样的,意思是我们可以随时把任何一个组件改成动态调用的方式.
不过目前 ng 支持的不是很好
-input, output (支持)
-tranclude (Projectable nodes 显然和 ng-content配合不上)
-在 component 上放指令 (动态创建的 component, 没办法加上指令, 这导致了 dynamic accessor 很难写)
例子
5. 一些常用到的类
-ViewContainerRef : 好比一个 root div, 通常我们引用它目的就是 append element 进去.
常用 : createEmbeddedView, createComponent, insert
-TemplateRef : 指的是 <template> 里面的内容.
常用 : createEmbeddedView
-ElementRef : dom
常用 : nativeElement (获取 dom 对象引用)
1. Jit
2. Aot
Jit 的情况下你可以动态的写组件模板, 最后 append 出去, 类似 ng1 的 $compile
Aot 的话, 模板是固定的, 我们只是可以动态创建 component 然后 append 出去
这一篇只会谈及 Aot
要知道的事项 :
1. 所有要动态的组件除了需要 declarations之外还要声明到 entryComponents 里头, 原因是 ng 是通过扫描模板来 import component class 的, 动态组件不会出现在模板上所以我们要用另一个 way 告诉 ng。
providers: [ {provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: [AComponentClass, BComponentClass], multi: true} ]
要方便扩展的话可以用 provides, ng-router 也是用这个实现的.
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 很难写)
例子
@Component({ templateUrl : "./debugTwo.component.html" }) export class DebugTwoComponent implements OnInit, AfterViewInit { constructor( private fb : FormBuilder, private cfr : ComponentFactoryResolver ) { } form : FormGroup @ViewChild("target", { read : ViewContainerRef }) target : ViewContainerRef ngOnInit() { this.form = this.fb.group({ age : [0] }); } ngAfterViewInit() { let factory = this.cfr.resolveComponentFactory(AccessorComponent); let component = this.target.createComponent(factory, 0); let ctrl = this.form.controls["age"]; component.instance.writeValue(ctrl.value); //需要手动去调用 writeValue, registerOnChange, registerOnTouched, 如果可以直接加上 formControlName 指令,就方便多了. component.instance.registerOnChange((v) => { ctrl.setValue(v); }); //component.instance.template = this.template; } }
5. 一些常用到的类
-ViewContainerRef : 好比一个 root div, 通常我们引用它目的就是 append element 进去.
常用 : createEmbeddedView, createComponent, insert
-TemplateRef : 指的是 <template> 里面的内容.
常用 : createEmbeddedView
-ElementRef : dom
常用 : nativeElement (获取 dom 对象引用)
相关文章推荐
- Angular学习笔记【如何正确使用第三方组件】
- angular2 学习笔记 ( Dynamic Component 动态组件)
- 强大的DataGrid组件[8]_内嵌ComboBox动态数据联动——Silverlight学习笔记[16]
- angular学习总结十一——动态创建组件并实现交互二
- Angular学习笔记(十六)组件周期钩子之投影和AfterContentInit
- UML学习笔记(2)之组件图,部署图以及动态模型的四种图
- Angular学习笔记(十三)之组件通讯输入/输出属性
- UML学习笔记(2)之组件图,部署图以及动态模型的四种图
- 学习u3d笔记(一) OnGui实现动态创建cube组件 并按钮控制cube旋转 停止 销毁
- angular学习总结十——动态创建组件并实现交互一
- Ionic学习笔记5_动态组件指令
- Angular学习笔记之集成第三方UI框架、组件
- Angular学习:模块和组件的动态加载
- 四大组件之Service的再学习笔记
- angularjs2 学习笔记(二) 组件
- react-native学习笔记——ViewStack组件
- web学习笔记19-静态代理,动态代理,spring AOP
- MFC学习笔记_动态创建1
- tinyos学习笔记13--PppRouter组件关系图
- ruby学习笔记(4)-动态修改类的属性