动态组件
问题1:动态组件和我们写的ngIf选择器有啥区别并且优势在哪里?
模板选择器直接实例化组件:
解释:根据已创建的组件工厂进行组件实例化,无须动态生成宿主元素(标签)
动态组件(工厂模式实例化组件)
解释:根据已经声明的组件(静态类d.ts)创建组件工厂再进行组件实例化,宿主元素(标签)通过Host文件生成
答:
先说场景:
(1)NG官网的例子一个广告位需要多个不同布局的页面进行切换,如果用ngIf,你就只能写死多个模板在父组件里(静态)。
(2)tab页切换,可以用上图动态组件生成的例子;(scm系统和wms系统的tab页看上去是路由锚点控制页面切换,但实际也是披着动态组件的羊毛)
两者对比:
(1)展现方面:没任何差别
(2)工作量:两者其实没什么差别,但同在一个父组件下基本都是传相同的参数值,那么你宁愿一个个写在模板上,还是写在方法里一劳永逸?
(3)性能:ngIf——我第一时间就想到了ngIf带来的注释模板,页面的变化都要进行变化检测,模板有多个ngIf模板就会多次判断(强行解释);其次这种懒加载方式能减少bundle的体积,加快首屏渲染速度
子问题1:enterComponents和声明组件区别? 答:declarations——通过模板的selector创建组件,即声明并创建;entryComponents——声明不创建,等到用的时候才通过离线模板编译器(OTC)根据entryComponents List的内容编译已声明的组件创建工厂,Angular使用entryComponents来启用“tree shaking”,即只编译项目中实际使用的组件,而不是编译所有在ngModule中声明但从未使用的组件,enterComponents在ng里有三种表现形式,
- 在
@NgModule.bootstrap
里声明的启动组件,如AppComponent。 - 在路由配置里引用的组件
- 其他通过编程使用组件类型加载的动态组件 (angular2(4) 中动态创建模块和组件的两种方案)
扩展:
一句话分析这张图片:ng的组件都是通过工厂函数(ComponentFactory<comp>)实例化出来,ngFactory.js文件负责装载组件模板及变化检测代码片段等静态数据,变量早已经在编译过程前开辟好内存空间,一切渲染过程都是以此为媒介。剩下的就是coder的选择是否用动态组件的方式加载,如果选用动态组件方式必定经过entryComponents的记录,当页面要加载这个组件时会OTC编译声明好的组件同时创建ngFactory.js 和 _Host_[x].ngFactory.js,前者渲染页面(考虑IOS和Android)后者负责生成宿主元素,这个就是一个动态组件编译过程。
其他:动态组件考点不止这些,还有装饰器@XXX、元数据的传入可以参考 Implementing custom component decorator ,
问题2:ng的依赖注入在软件开发解决什么?
答:依赖注入(Dependence Inject)是控制反转(Inversion of Control 后)的行为。
控制反转——好莱坞的法则:“don‘t call us, we‘ll call you”。
紧耦合,谁也不能缺少谁,对象或者模块间通过互new的形式存在
实际场景,复杂且不好管理。
引入第三方把相应的对象/类(ng以服务形式存在)统一管理,并按需注入
最后,达到解耦的理想状态
问题3:依赖注入不仅仅是调用服务,实战还有更多新玩法。
概念篇——1、创建服务过程选择@Injectable、@NgModule 还是 @Component ?
2、provider入口API及各种提供商(useClass比较常见,适用于内部固定,外部变化多。useFactory对于权限控制即时变更状态场景有用)
3、每个组件创建一个注入器实例,服务实例在应用中是注册多次还是仅有一次,是根据注入形式不同前者是@Component.provider后者是AppModule.provider (举例:多种编辑会话,每个组件需要一个特定的服务进行管理表单的新值和旧值,这种情况必须使用@Component.provider,你可以理解为AppModule.provider注册的就只有一个对象(单例),根模块的提供商是向下传递到有需要用到该服务的组件中,而@Component.provider是为每个组件实例化独立的服务)
实践篇——1、组件可以通过注入器,把自己注入到子组件上(服务=类)
2、类-接口写法{provider: virtual, useClass: realClass},为了节省内存,同时作为Token而存在
3、出现引用循环,立即想到[{ provide: Parent, useExisting: forwardRef(() => AlexComponent) }]
4、仅找上一级的注入器服务添加@Host() 在服务创建前写 @Host() private heroCache: HeroCacheService,防止服务没找到用@Optional()
疑问:angular既然选择了AOT编译,那么离线模板编译器(OTC)在客户端是以什么形式存在?代码片段?
动态组件模块相关文章
Angular进阶:Angular编译机制(AOT、JIT)
Implementing custom component decorator
30行代码让你理解angular依赖注入:angular 依赖注入原理