Angular中的多级依赖注入如何设计


本篇内容介绍了“Angular中的多级依赖注入如何设计”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前面我们说过,Angular 中的注入器是可继承、且分层的。在 Angular 中,有两个注入器层次结构:ModuleInjector模块注入器:使用@NgModule()@Injectable()注解在此层次结构中配置ModuleInjectorElementInjector元素注入器:在每个 DOM 元素上隐式创建模块注入器和元素注入器都是树状结构的,但它们的分层结构并不完全一致。模块注入器的分层结构,除了与应用中模块设计有关系,还有平台模块(PlatformModule)注入器与应用程序模块(AppModule)注入器的分层结构。在 Angular 术语中,平台是供 Angular 应用程序在其中运行的上下文。Angular 应用程序最常见的平台是 Web 浏览器,但它也可以是移动设备的操作系统或 Web 服务器。Angular 应用在启动时,会创建一个平台层:平台是 Angular 在网页上的入口点,每个页面只有一个平台页面上运行的每个 Angular 应用程序,所共有的服务都在平台内绑定一个 Angular 平台,主要包括创建模块实例、销毁等功能:实际上,平台在启动的时候(bootstrapModuleFactory方法中),在ngZone.run中创建ngZoneInjector,以便在 Angular 区域中创建所有实例化的服务,而ApplicationRef(页面上运行的 Angular 应用程序)将在 Angular 区域之外创建。在浏览器中启动时,会创建浏览器平台:使用平台工厂(例如上面的createPlatformFactory)创建平台时,将隐式初始化页面的平台:通过以上过程,我们知道 Angular 应用在创建平台的时候,创建平台的模块注入器ModuleInjector。我们从上一节Injector定义中也能看到,NullInjector是所有注入器的顶部:因此,在平台模块注入器之上,还有NullInjector()。而在平台模块注入器之下,则还有应用程序模块注入器。每个应用程序有至少一个 Angular 模块,根模块就是用来启动此应用的模块:AppModule根应用模块由BrowserModule重新导出,当我们使用 CLI 的new命令创建新应用时,它会自动包含在根AppModule中。应用程序根模块中,提供者关联着内置的 DI 令牌,用于为引导程序配置根注入器。Angular 还将ComponentFactoryResolver添加到根模块注入器中。此解析器存储了entryComponents系列工厂,因此它负责动态创建组件。到这里,我们可以简单地梳理出模块注入器的层级关系:模块注入器树的最上层则是应用程序根模块(AppModule)注入器,称作 root。在 root 之上还有两个注入器,一个是平台模块(PlatformModule)注入器,一个是NullInjector()。因此,模块注入器的分层结构如下:在我们实际的应用中,它很可能是这样的:Angular DI 具有分层注入体系,这意味着下级注入器也可以创建它们自己的服务实例。前面说过,在 Angular 中有两个注入器层次结构,分别是模块注入器和元素注入器。当 Angular 中懒加载的模块开始广泛使用时,出现了一个 issue:依赖注入系统导致懒加载模块的实例化加倍。在这一次修复中,引入免费云主机域名了新的设计:注入器使用两棵并行的树,一棵用于元素,另一棵用于模块。Angular 会为所有entryComponents创建宿主工厂,它们是所有其他组件的根视图。这意味着每次我们创建动态 Angular 组件时,都会使用根数据RootData)创建根视图(RootView):该根数据RootData)包含对elInjectorngModule注入器的引用:引入元素注入器树,原因是这样的设计比较简单。通过更改注入器层次结构,避免交错插入模块和组件注入器,从而导致延迟加载模块的双倍实例化。因为每个注入器都只有一个父对象,并且每次解析都必须精确地寻找一个注入器来检索依赖项。在 Angular 中,视图是模板的表示形式,它包含不同类型的节点,其中便有元素节点,元素注入器位于此节点上:默认情况下ElementInjector为空,除非在@Directive()@Component()providers属性中进行配置。当 Angular 为嵌套的 HTML 元素创建元素注入器时,要么从父元素注入器继承它,要么直接将父元素注入器分配给子节点定义。如果子 HTML 元素上的元素注入器具有提供者,则应该继承该注入器。否则,无需为子组件创建单独的注入器,并且如果需要,可以直接从父级的注入器中解决依赖项。那么,元素注入器与模块注入器是从哪个地方开始成为平行树的呢?我们已经知道,应用程序根模块(AppModule)会在使用 CLI 的new命令创建新应用时,自动包含在根AppModule中。当应用程序(ApplicationRef)启动(bootstrap)时,会创建entryComponent:该过程会使用根数据(RootData)创建根视图(RootView),同时会创建根元素注入器,在这里elInjectorInjector.NULL。在这里,Angular 的注入器树被分成元素注入器树和模块注入器树,这两个平行的树了。Angular 会有规律的创建下级注入器,每当 Angular 创建一个在@Component()中指定了providers的组件实例时,它也会为该实例创建一个新的子注入器。类似的,当在运行期间加载一个新的NgModule时,Angular 也可以为它创建一个拥有自己的提供者的注入器。子模块和组件注入器彼此独立,并且会为所提供的服务分别创建自己的实例。当 Angular 销毁NgModule或组件实例时,也会销毁这些注入器以及注入器中的那些服务实例。上面我们介绍了 Angular 中的两种注入器树:模块注入器树和元素注入器树。那么,Angular 在提供依赖时,又会以怎样的方式去进行解析呢。在 Angular 种,当为组件/指令解析 token 获取依赖时,Angular 分为两个阶段来解析它:针对ElementInjector层次结构(其父级)针对ModuleInjector层次结构(其父级)其过程如下(参考多级注入器-解析规则):当组件声明依赖项时,Angular 会尝试使用它自己的ElementInjector来满足该依赖。如果组件的注入器缺少提供者,它将把请求传给其父组件的ElementInjector。这些请求将继续转发,直到 Angular 找到可以处理该请求的注入器或用完祖先ElementInjector。如果 Angular 在任何ElementInjector中都找不到提供者,它将返回到发起请求的元素,并在ModuleInjector层次结构中进行查找。如果 Angular 仍然找不到提供者,它将引发错误。为此,Angular 引入一种特殊的合并注入器。合并注入器本身没有任何值,它只是视图和元素定义的组合。当 Angular 解析依赖项时,合并注入器则是元素注入器树和模块注入器树之间的桥梁。当 Angular 尝试解析组件或指令中的某些依赖关系时,会使用合并注入器来遍历元素注入器树,然后,如果找不到依赖关系,则切换到模块注入器树以解决依赖关系。注入器是可继承的,这意味着如果指定的注入器无法解析某个依赖,它就会请求父注入器来解析它。具体的解析算法在resolveDep()方法中实现:如果是这样模板的根AppComponent组件,那么在 Angular 中将具有三个视图:依赖解析过程,解析算法会基于视图层次结构,如图所示进行:如果在子组件中解析某些令牌,Angular 将:首先查看子元素注入器,进行检查elRef.element.allProviders|publicProviders。然后遍历所有父视图元素(1),并检查元素注入器中的提供者。如果下一个父视图元素等于null(2),则返回到startView(3),检查startView.rootData.elnjector(4)。只有在找不到令牌的情况下,才检查startView.rootData module.injector( 5 )。由此可见,Angular 在遍历组件以解析某些依赖性时,将搜索特定视图的父元素而不是特定元素的父元素。视图的父元素可以通过以下方法获得:“Angular中的多级依赖注入如何设计”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注百云主机网站,小编将为大家输出更多高质量的实用文章!

相关推荐: 微信小程序Component构造器怎么用

小编给大家分享一下微信小程序Component构造器怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!    Component构造器可用于定义组件,调用Component构造器时…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 08/15 16:51
下一篇 08/15 16:51

相关推荐