深入了解Angular中的依赖注入模式(玩法案例)_第1页
深入了解Angular中的依赖注入模式(玩法案例)_第2页
深入了解Angular中的依赖注入模式(玩法案例)_第3页
深入了解Angular中的依赖注入模式(玩法案例)_第4页
深入了解Angular中的依赖注入模式(玩法案例)_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第深入了解Angular中的依赖注入模式(玩法案例)模块注入器:在@NgModule的元数据属性里可以配置providers,还可以使用v6以后提供的@Injectable声明provideIn声明为模块名、root等。(实际上在root根模块之上还有两个注入器,Platform和Null,这里不讨论它们。)

元素注入器:在组件@Component的元数据属性里可以配置providers,viewProviders,或者在指令的@Directive元数据里的providers.

另外,实际上@Injectable装饰器除了用了声明模块注入器外,也可以声明为元素注入器。更经常会将其声明为在root提供,以实现单例。它通过类自己集成元数据来避免模块或者组件直接显式声明provider,这样如果该类没有任何组件指令服务等类注入它,就没有代码链接到该类型声明,就可以被编译器忽略,从而实现了摇树。

还有一种提供方法是声明InjectionToken的时候直接给出值。

这里给出这几种方式的速写模板:

@NgModule({providers:[

//模块注入器

exportclassMyModule{}

@Component({providers:[

//元素注入器-组件

viewProviders:[

//元素注入器-组件视图

exportclassMyComponent{}

@Directive({providers:[

//元素注入器-指令

exportclassMyDirective{}

@Injectable({

providedIn:root

exportclassMyService{}

exportconstMY_INJECT_TOKEN=newInjectionTokenMyClass(my-inject-token,{

providedIn:root,

factory:()={

returnnewMyClass();

});

提供依赖的位置不同的选择会带来一些差异,最终影响着包的大小,依赖的能被注入的范围和依赖的生命周期。对于不同的场景,如单例(root),服务隔离(module),多重编辑窗(component)等都有不同的适用方案,应当选择合理的位置,避免共享的信息不当,或者代码打包的冗余。

2.3多样的值函数工具

如果只是提供实例的注入,那还显示不出Angular框架依赖注入的灵活性。Angular提供了很多灵活的注入工具,useClass自动创建新实例,useValue使用静态值,useExisting可以复用已有的实例,useFactory通过函数来构造,搭配指定deps指定构造函数参数,这些组合起来玩法可以非常花样。可以半路截胡一个类的token令牌替换成另一个自己准备好的实例,可以造一个token先保存起来值或者实例,然后再在后面需要用到的时候重新替换回去,甚至可以用工厂函数返回实例的局部信息实现映射成另一个对象或者属性值。这里的玩法会通过后面的案例进行阐述,这里就先不展开。官网也有很多例子可以参考。

2.4注入消费和装饰器

Angular中的注入可以在构造函数constructor内注入,也可以拿到注入器injector通过get方法获取已有的注入元素。

Angular支持在注入的时候增加装饰器进行标记,

@Host()来限制冒泡

@Self()限制为元素自身

@SkipSelf()限制为元素自身以上

@Optional()标记为可选

@Inject()限制为自定义Token令牌

这里有一篇文章《@Selfor@Optional@HostThevisualguidetoAngularDIdecorators.》非常生动形象地展示父子组件间如果使用了不同的装饰器,最后会命中的实例有什么不同。

图3不同注入装饰器的筛选结果

2.4.1补充:宿主视图和@Host

这几个装饰器里面,最不好理解的可能就是@Host了,这里补充一些@Host的具体说明。官方对@Host装饰器的解释是

...retrieveadependencyfromanyinjectoruntilreachingthehostelement

Host在这里是宿主的意思,@Host这个装饰器将会限定查询的范围在宿主元素(hostelement)以内。什么是宿主元素呢?假如B组件是A组件模板使用的组件,那么A组件实例就是B组件实例的宿主元素。组件模板产生的内容称为View(视图),同一个View对于不同组件来说可能是不同视图。如果A组件在自己的template范围内使用B组件(见图4),A的模板内容形成的视图(红框部分)对A组件来说就是A的内嵌视图,B组件在这个视图内,所以对B来说这个视图就是B的宿主视图。装饰器@Host就是限定搜索范围为宿主视图之内,找不到不会再进行冒泡了。

图4内嵌视图和宿主视图

3案例和玩法

下面我们通过真实的案例,来看看依赖注入到底是怎么运转起来的,怎么排查错误,以及还能怎么玩。

3.1案例一:模态窗创建动态组件,找不到组件问题

DevUI组件库的模态窗组件提供了一个服务ModalService,该服务可以弹出一个模态框,而且可以配置为自定义的组件。业务的同学经常在使用这个组件的时候报错,包找不到自定义的组件。

比如以下的报错:

图5使用ModalService的时候创建引用EditorX的组件的报错找不到对应服务提供商

分析ModalService是如何创建自定义组件的,ModalService源码Open函数第52行和第95行。能看到,componentFactoryResolver如果没有传入就使用ModalService注入的componentFactoryResolver。而大多数情况下,业务会在根模块引入一次DevUI

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论