Angular的后院:组件依赖关系的解决
by Dor Moshe
通過Dor Moshe
Angular的后院:解決 組件依賴關(guān)系 (Angular’s Backyard: The Resolving of Components Dependencies)
This article originally appeared on dormoshe.io
這篇文章 最初出現(xiàn)在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的分層依賴注入機(jī)制。 我們通過服務(wù)或組件使用它來解析另一個(gè)服務(wù)或提供者。 但是,我們知道Angular為了解決依賴關(guān)系做什么嗎? 可能不是,因?yàn)锳ngular會(huì)照顧我們需要將其用作黑匣子的情況。
In this article, we’ll open the black box and explore the code of the component dependencies resolution mechanism.
在本文中,我們將打開黑盒,并探索組件依賴關(guān)系解析機(jī)制的代碼。
回到基礎(chǔ) (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)是一種用于管理代碼依賴關(guān)系的強(qiáng)大模式。 Angular的DI系統(tǒng)可以 “及時(shí)” 創(chuàng)建并提供相關(guān)服務(wù) 。 Angular有自己的DI框架,沒有它我們就無法構(gòu)建Angular應(yīng)用程序。
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系統(tǒng)實(shí)際上是一個(gè)層次結(jié)構(gòu) 系統(tǒng)。 該系統(tǒng)支持與組件樹并行的嵌套進(jìn)樣器。 注入程序使用提供程序創(chuàng)建依賴關(guān)系。 我們可以在該組件樹的任何級(jí)別重新配置注入器。 在幕后,每個(gè)組件都使用為該組件本身定義的零個(gè),一個(gè)或多個(gè)提供程序來設(shè)置自己的注入器 。
解決順序 (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對(duì)依存關(guān)系的解析具有順序。 當(dāng)組件請(qǐng)求依賴項(xiàng)時(shí),如果它存在于@Component.providers數(shù)組(組件注入器)中,則將提供此依賴項(xiàng)。
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繼續(xù)使用父組件注入器并一次又一次地檢查。 如果Angular找不到祖先,它將通過應(yīng)用程序主注入器提供此依賴關(guān)系。 這是分層DI機(jī)制的核心概念。
讓我們看一下代碼 (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實(shí)例化組件時(shí),它將調(diào)用resolveDep函數(shù)。 該函數(shù)的簽名包含組件視圖容器,元素,依賴項(xiàng)定義和更多參數(shù)。 我們將專注于組件視圖和依賴對(duì)象。 依賴性對(duì)象僅包含組件的一種依賴性。
Here is the resolveDep function skeleton from the Angular GitHub repository:
這是Angular GitHub存儲(chǔ)庫中的resolveDep函數(shù)框架:
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.
函數(shù)框架包含分辨率的主要概念,不包含邊緣情況。 完整的代碼可以在這里找到。 在接下來的部分中,我們將探索功能框架。
保沙 (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.
感嘆號(hào)是Typescript 2.0的新功能。 ! 在類型檢查器無法得出結(jié)論的上下文中,可以使用后綴表達(dá)式運(yùn)算符來斷言其操作數(shù)是非null且未定義的。 Angular經(jīng)常使用此功能,因此我們不用擔(dān)心。
第1部分-準(zhǔn)備 (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; 代碼將原始視圖(組件的視圖容器)保存在一個(gè)變量中,因?yàn)関iew變量將很快更改。
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或依賴項(xiàng)鍵,例如HeroService_4 。 該鍵由依賴項(xiàng)名稱和生成的數(shù)字構(gòu)建,以唯一地處理依賴項(xiàng)。
第2部分-源組件和祖先搜索 (Part 2 —Source component and Ancestors search)
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循環(huán)實(shí)現(xiàn)檢查源@Component.providers和祖先組件的階段。 根據(jù)依賴性令牌密鑰,將在第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行,則源組件滿足依賴性。 因此,如果依賴關(guān)系是在過去的第6行實(shí)例化的,則實(shí)例將在第10行由resolveDep函數(shù)返回。如果這是組件或其子級(jí)第一次請(qǐng)求依賴關(guān)系,它將在第7行創(chuàng)建,然后將由第10行的resolveDep函數(shù)返回。
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組件注入器中未找到依賴項(xiàng),則elDef = viewParentEl(view) !; 和view = view.parent !; 將被調(diào)用以將變量前進(jìn)到父元素。 while循環(huán)將繼續(xù)運(yùn)行,直到在祖先注入器中找到相關(guān)性為止。 如果在檢查所有祖先后仍未找到依賴項(xiàng),則while循環(huán)將結(jié)束,并且第三部分將開始起作用。
第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.
如果源組件或其祖先組件之一是由路由器出口(路由器組件)加載的,則根注入器為出口注入器 。 該注入器提供了一些依賴性,例如路由器服務(wù)。 否則,根注入器是自舉組件的注入器。
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行找到依賴項(xiàng),那么resolveDep函數(shù)將返回該值。 在其他情況下,第4部分將生效。
第4部分-應(yīng)用模塊注入器 (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);
當(dāng)涉及到這一部分時(shí),這意味著第2部分和第3部分不能滿足依賴關(guān)系。這是滿足依賴關(guān)系的最后機(jī)會(huì)。 這部分的代碼試圖從應(yīng)用程序模塊注入器或根模塊獲取依賴關(guān)系。 此模塊包含應(yīng)用程序范圍的依賴項(xiàng): 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流程。 如果找不到依賴關(guān)系,則Angular無法滿足此依賴關(guān)系,因此應(yīng)引發(fā)異常。
結(jié)論 (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所依賴的一項(xiàng)核心功能。 有時(shí),解析過程看起來很復(fù)雜且漫長。 離開Angular管理此流程并享受易用性非常方便。 現(xiàn)在,當(dāng)我們?cè)诮M件依賴關(guān)系解決方案的后院爬升之后,我們知道使用它時(shí)會(huì)發(fā)生什么。
You can follow me on dormoshe.io or Twitter to read more about Angular, JavaScript and web development.
您可以在dormoshe.io或Twitter上關(guān)注我,以了解有關(guān)Angular,JavaScript和Web開發(fā)的更多信息。
翻譯自: https://www.freecodecamp.org/news/angulars-backyard-the-resolving-of-component-dependencies-2015b40e5bd1/
總結(jié)
以上是生活随笔為你收集整理的Angular的后院:组件依赖关系的解决的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开发人员避免编写测试的2个最常见原因
- 下一篇: 梦到冲浪什么意思