Angular的后院:组件依赖关系的解决

by Dor Moshe

通过Dor Moshe

Angular的后院:解决 组件依赖关系 (Angular’s Backyard: The Resolving of Components Dependencies)

This article originally appeared on dormoshe.io

这篇文章 最初出现在dormoshe.io

Many of us use the Hierarchical Dependency Injection mechanism of Angular. We use it through a service or a component to resolve another service or provider. But, do we know what Angular does in order to resolve the dependencies? Probably not, because Angular takes care of what we need to use it as a black box.

我们中的许多人都使用Angular的分层依赖注入机制。 我们通过服务或组件使用它来解析另一个服务或提供者。 但是,我们知道Angular为了解决依赖关系做什么吗? 可能不是,因为Angular会照顾我们需要将其用作黑匣子的情况。

In this article, we’ll open the black box and explore the code of the component dependencies resolution mechanism.

在本文中,我们将打开黑盒,并探索组件依赖关系解析机制的代码。

回到基础 (Back to the basics)

Dependency Injection (DI) is a powerful pattern for managing code dependencies. Angular’s DI system creates and delivers dependent services “just-in-time”. Angular has its own DI framework, and we can’t build an Angular application without it.

依赖注入 (DI)是一种用于管理代码依赖关系的强大模式。 Angular的DI系统可以 “及时” 创建并提供相关服务 。 Angular有自己的DI框架,没有它我们就无法构建Angular应用程序。

The Angular DI system is actually a Hierarchical system. This system supports nested injectors in parallel with the component tree. An injector creates dependencies using providers. We can reconfigure the injectors at any level of that component tree. Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself.

Angular DI系统实际上是一个层次结构 系统。 该系统支持与组件树并行的嵌套进样器。 注入程序使用提供程序创建依赖关系。 我们可以在该组件树的任何级别重新配置注入器。 在幕后,每个组件都使用为该组件本身定义的零个,一个或多个提供程序来设置自己的注入器

解决顺序 (Resolution Order)

The hierarchical DI has an order to the resolution of the dependencies. When a component requests a dependency, if it exists in the @Component.providers array (the component injector), then this dependency will be supplied.

层次化DI对依存关系的解析具有顺序。 当组件请求依赖项时,如果它存在于@Component.providers数组(组件注入器)中,则将提供此依赖项。

Elsewhere, Angular continues to the parent component injector and checks again and again. If Angular doesn’t find an ancestor, it will supply this dependency via the application main injector. This is the core concept of the hierarchical DI mechanism.

在其他地方,Angular继续使用父组件注入器并一次又一次地检查。 如果Angular找不到祖先,它将通过应用程序主注入器提供此依赖关系。 这是分层DI机制的核心概念。

让我们看一下代码 (Let’s see the code)

When Angular instantiates a component, it calls the resolveDep function. This function's signature contains the component view container, the element, the dependency definition and some more arguments. We will focus on the component view and the dependency object. The dependency object contains only one dependency of the component.

Angular实例化组件时,它将调用resolveDep函数。 该函数的签名包含组件视图容器,元素,依赖项定义和更多参数。 我们将专注于组件视图和依赖对象。 依赖性对象仅包含组件的一种依赖性。

Here is the resolveDep function skeleton from the Angular GitHub repository:

这是Angular GitHub存储库中的resolveDep函数框架:

The function skeleton contains the main concepts of the resolution, without the edge cases. The full code can be found here. In the next parts, we will explore the function skeleton.

函数框架包含分辨率的主要概念,不包含边缘情况。 完整的代码可以在这里找到。 在接下来的部分中,我们将探索功能框架。

保沙 (Pausa)

The Exclamation mark is a new feature of Typescript 2.0. The ! post-fix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact. Angular uses this feature frequently, so we should not be afraid.

感叹号是Typescript 2.0的新功能。 ! 在类型检查器无法得出结论的上下文中,可以使用后缀表达式运算符来断言其操作数是非null且未定义的。 Angular经常使用此功能,因此我们不用担心。

第1部分-准备 (Part 1 — Preparation)

The const startView = view; code saves the original view (the view container of the component) in a variable because the view variable will change soon.

const startView = view; 代码将原始视图(组件的视图容器)保存在一个变量中,因为view变量将很快更改。

The const tokenKey = depDef.tokenKey; code fetches the tokenKey or the dependency key, for example, HeroService_4. This key builds by the dependency name and a generated number to handle the dependency uniquely.

const tokenKey = depDef.tokenKey; 代码获取tokenKey或依赖项键,例如HeroService_4 。 该键由依赖项名称和生成的数字构建,以唯一地处理依赖项。

The while loop implements the stages of checking the source @Component.providers and the ancestor components. According to the dependency token key, the source component providers will be checked in lines 1–3:

while循环实现检查源@Component.providers和祖先组件的阶段。 根据依赖性令牌密钥,将在第1–3行中检查源组件提供者:

If the provider exists on line 4, then the source component satisfies the dependency. So, if the dependency was instantiated in the past on line 6, the instance will return by the resolveDep function at line 10. If this is the first time that the component or its children ask for the dependency it will be created at line 7 and will return by the resolveDep function at line 10.

如果提供程序存在于第4行,则源组件满足依赖性。 因此,如果依赖关系是在过去的第6行实例化的,则实例将在第10行由resolveDep函数返回。如果这是组件或其子级第一次请求依赖关系,它将在第7行创建,然后将由第10行的resolveDep函数返回。

If the dependency is not found in the view component injector, the elDef = viewParentEl(view) !; and view = view.parent !; will be called to advance the variable to the parent element. The while loop will continue running until the dependency is found in the ancestor injector. If the dependency is still not found after checking all ancestors, the while loop will end and the third part will come into action.

如果在view组件注入器中未找到依赖项,则elDef = viewParentEl(view) !;view = view.parent !; 将被调用以将变量前进到父元素。 while循环将继续运行,直到在祖先注入器中找到相关性为止。 如果在检查所有祖先后仍未找到依赖项,则while循环将结束,并且第三部分将开始起作用。

第3部分-根注射器 (Part 3 — Root injector)

If come to this part, the dependency can’t be satisfied by any of the component ancestors injectors. Then the startView or the source component will be checked at line 1:

如果涉及到这一部分,则任何组件祖先注入器都无法满足这种依赖性。 然后将在第1行检查startView或源组件:

If the source component or one of its ancestor components was loaded by the Router Outlet (the router component), the root injector is the Outlet Injector. This injector supplies some dependencies like the Router service. Otherwise, the root injector is the bootstrap component’s injector.

如果源组件或其祖先组件之一是由路由器出口(路由器组件)加载的,则注入器为出口注入器 。 该注入器提供了一些依赖性,例如路由器服务。 否则,根注入器是自举组件的注入器。

If the dependency is found at line 3, then the value will be returned by the resolveDep function. In the other case, part 4 will come into action.

如果在第3行找到依赖项,那么resolveDep函数将返回该值。 在其他情况下,第4部分将生效。

第4部分-应用模块注入器 (Part 4 — Application module injector)

When we come to this part, it means that the dependency can’t be satisfied by part 2 and part 3. This is the last chance to satisfy the dependency. This part’s code tries to get the dependency from the application module injector or the root module. This module contains the application-wide dependencies:return startView.root.ngModule.injector.get(depDef.token,notFoundValue);

当涉及到这一部分时,这意味着第2部分和第3部分不能满足依赖关系。这是满足依赖关系的最后机会。 这部分的代码试图从应用程序模块注入器或根模块获取依赖关系。 此模块包含应用程序范围的依赖项: return startView.root.ngModule.injector.get(depDef.token,notFoundValue);

This part finishes the resolveDep flow. If the dependency is not found, then Angular can’t satisfy this dependency and it should throw an exception.

本部分完成resolveDep流程。 如果找不到依赖关系,则Angular无法满足此依赖关系,因此应引发异常。

结论 (Conclusion)

The Hierarchical DI is a core feature that Angular leans on a lot. Sometimes, the resolution process looks complicated and long. It’s very convenient to leave Angular to manage this flow and enjoy the ease of use. Now, after we hiked in the backyard of the component dependency resolution, we know what to expect when we use it.

分层DI是Angular所依赖的一项核心功能。 有时,解析过程看起来很复杂且漫长。 离开Angular管理此流程并享受易用性非常方便。 现在,当我们在组件依赖关系解决方案的后院爬升之后,我们知道使用它时会发生什么。

You can follow me on dormoshe.io or Twitter to read more about Angular, JavaScript and web development.

您可以在dormoshe.io或Twitter上关注我,以了解有关Angular,JavaScript和Web开发的更多信息。

翻译自: https://www.freecodecamp.org/news/angulars-backyard-the-resolving-of-component-dependencies-2015b40e5bd1/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/395817.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

node中的Stream-Readable和Writeable解读

在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream。Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream、Reader、OutputStream、Writer,其中InputStream和OutputSt…

新Rider预览版发布,对F#的支持是亮点

JetBrains一直在改进自己的跨平台.NET IDE产品Rider,努力使其成为Visual Studio家族产品可承担职能的重要替代者。于今年四月发布的Rider预览版(EAP 21)提供了一些新特性,其中的亮点在于对函数式编程语言F#的支持。\\鉴于这是Ride…

java代码整合_java合并多个文件的实例代码

在实际项目中,在处理较大的文件时,常常将文件拆分为多个子文件进行处理,最后再合并这些子文件。下面就为各位介绍下Java中合并多个文件的方法。Java中合并子文件最容易想到的就是利用BufferedStream进行读写。具体的实现方式如下,…

正则表达式的一些规则

1.限定修饰符只对其紧前的元字符有效 String rex8 "\\d\\D"; 上式中,只对\\D有效,即有至少有1个(1个或多个)非数字,\\d仍然只许有一个数字。 2.[1,2,3]和[123]是一样的转载于:https://www.cnblogs.com/Sabr…

2016版单词的减法_在2016年最大的电影中,女性只说了27%的单词。

2016版单词的减法by Amber Thomas通过琥珀托马斯 在2016年最大的电影中,女性只说了27%的单词。 (Women only said 27% of the words in 2016’s biggest movies.) Movie trailers in 2016 promised viewers so many strong female characters. Jyn Erso…

软件工程博客---团队项目---个人设计2(算法)

针对分析我们团队项目的需求,我们选定Dijkstra算法。 算法的基本思想: Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它应用了贪心算法模式,是目前公认的最好的求解最短路径的方法。算法解决的是有向…

UWP 杂记

UWP用选取文件对话框 http://blog.csdn.net/u011033906/article/details/65448394 文件选取器、获取文件属性、写入和读取、保存读取和删除应用数据 https://yq.aliyun.com/articles/839 UWP判断文件是否存在 http://blog.csdn.net/lindexi_gd/article/details/51387901…

微信上传素材 java_微信素材上传(JAVA)

public String uploadMaterial(String url,InputStream sbs,String filelength,String filename, String type) throws Exception {try {DataInputStream innew DataInputStream(sbs);url url.replace("TYPE", type);URL urlObj new URL(url);// 创建Http连接HttpU…

SQL Server读写分离之发布订阅

一、发布 上面有多种发布方式,这里我选择事物发布,具体区别请自行百度。 点击下一步、然后继续选择需要发布的对象。 如果需要筛选发布的数据点击添加。 根据自己的计划选择发布的时间。 点击安全设置,设置代理信息。 最后单击完成系统会自动…

码农和程序员的几个重要区别!

如果一个企业老板大声嚷嚷说,“我要招个程序员”,那么十之八九指的是“码农”——一种纯粹为了钱而写代码的技术人员。这其实是一种非常狭隘和错误的做法,原因么,且听我一一道来。1、码农写代码,程序员写系统从本质上讲…

sql server2008禁用远程连接

1.打开SQL Server 配置管理器,双击左边 SQL Server 网络配置,点击TCP/IP协议,在协议一栏中,找到 全部侦听,修改为否,然后点击IP地址,将IP地址为127.0.0.1(IPV4)或::1(IPV6)的已启用修改为是,其它的IP地址的已启用修改为否 注意:如…

snapchat注册不到_从Snapchat获得开发人员职位中学到的经验教训

snapchat注册不到Here are three links worth your time:这是三个值得您花费时间的链接: I just got a developer job at Snapchat. Here’s what I learned and how it can help you with your job search (15 minute read) 我刚刚在Snapchat获得开发人员职位。 这…

java bitmap jar_Java面试中常用的BitMap代码

引言阿里内推面试的时候被考了一道编程题:10亿个范围为1~2048的整数,将其去重并计算数字数目。我看到这个题目就想起来了《编程珠玑》第一章讲的叫做BitMap的数据结构,但是我并没有在java上实现过,这就比较尴尬了,再加…

移动端工程架构与后端工程架构的思想摩擦之旅(1)

此文已由作者黎星授权网易云社区发布。欢迎访问网易云社区,了解更多网易技术产品运营经验记资源投放后端工程的架构调整与优化 架构思考一直以来对软件工程架构有着极大的兴趣,无论是之前负责的移动端Android工程,亦或是现在转到后端开发后维…

View野指针问题分析报告

【问题描述】 音乐组同事反馈了一个必现Native Crash问题&#xff0c;tombstone如下&#xff1a; pid: 5028, tid: 5028, name: com.miui.player >>> com.miui.player <<< signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 79801f28r0 7ac59c98 r1 …

SicilyFunny Game

一、题目描述 Two players, Singa and Suny, play, starting with two natural numbers. Singa, the first player, subtracts any positive multiple of the lesser of the two numbers from the greater of the two numbers, provided that the resulting number must be non…

java 分布式同步_Java Web分布式集群搭建(三)——Session同步

对于一个业务系统的Tomcat集群来说&#xff0c;必须保证同一个用户访问到任一台服务器上都可以维持之前操作的身份。比如在服务器A进行了登陆&#xff0c;那么在服务器B中也要同步该用户已登录的状态&#xff0c;这里就用到了Session的同步。同步方式sticky模式、复制模式、Ter…

移动应用程序和网页应用程序_如何不完全破坏您的移动应用程序的用户界面

移动应用程序和网页应用程序by Luke Konior卢克科尼尔(Luke Konior) 如何不完全破坏您的移动应用程序的用户界面 (How to not utterly ruin your mobile app’s user interface) There’s no single universal formula for designing a great user interface (if you discover…

logging记录日志

日志是一个系统的重要组成部分&#xff0c;用以记录用户操作、系统运行状态和错误信息。日志记录的好坏直接关系到系统出现问题时定位的速度。logging模块Python2.3版本开始成为Python标准库的一部分。 日志级别 在最简单的使用中&#xff0c;我们直接导入logging模块&#xff…

C#编程之接口

1.定义 接口是把公共方法和属性组合起来&#xff0c;以封装特定功能的一个集合。&#xff08;一旦定义了接口&#xff0c;就可以在类中实现它。这样类就可以支持接口所指定的所有属性和成员&#xff09; 注意1&#xff1a;接口不能单独存在。不能像实例化一个类那样实例化一个接…