Angular9 提供依賴

2020-07-03 14:05 更新

提供者就是一本說明書,用來指導(dǎo)依賴注入系統(tǒng)該如何獲取某個(gè)依賴的值。 大多數(shù)情況下,這些依賴就是你要?jiǎng)?chuàng)建和提供的那些服務(wù)。

提供服務(wù)

如果你是用 Angular CLI 創(chuàng)建的應(yīng)用,那么可以使用下列 CLI 的 ng generate 命令在項(xiàng)目根目錄下創(chuàng)建一個(gè)服務(wù)。把其中的 User 替換成你的服務(wù)名。

ng generate service User

該命令會(huì)創(chuàng)建下列 UserService 骨架:

Path:"src/app/user.service.ts" 。

import { Injectable } from '@angular/core';


@Injectable({
  providedIn: 'root',
})
export class UserService {
}

現(xiàn)在,你就可以在應(yīng)用中到處注入 UserService 了。

該服務(wù)本身是 CLI 創(chuàng)建的一個(gè)類,并且加上了 @Injectable() 裝飾器。默認(rèn)情況下,該裝飾器是用 providedIn 屬性進(jìn)行配置的,它會(huì)為該服務(wù)創(chuàng)建一個(gè)提供者。在這個(gè)例子中,providedIn: 'root' 指定 Angular 應(yīng)該在根注入器中提供該服務(wù)。

提供者的作用域

當(dāng)你把服務(wù)提供者添加到應(yīng)用的根注入器中時(shí),它就在整個(gè)應(yīng)用程序中可用了。 另外,這些服務(wù)提供者也同樣對(duì)整個(gè)應(yīng)用中的類是可用的 —— 只要它們有供查找用的服務(wù)令牌。

你應(yīng)該始終在根注入器中提供這些服務(wù) —— 除非你希望該服務(wù)只有在消費(fèi)方要導(dǎo)入特定的 @NgModule 時(shí)才生效。

providedIn 與 NgModule

也可以規(guī)定某個(gè)服務(wù)只有在特定的 @NgModule 中提供。比如,如果你希望只有當(dāng)消費(fèi)方導(dǎo)入了你創(chuàng)建的 UserModule 時(shí)才讓 UserService 在應(yīng)用中生效,那就可以指定該服務(wù)要在該模塊中提供:

Path:"src/app/user.service.ts" 。

import { Injectable } from '@angular/core';
import { UserModule } from './user.module';


@Injectable({
  providedIn: UserModule,
})
export class UserService {
}

上面的例子展示的就是在模塊中提供服務(wù)的首選方式。之所以推薦該方式,是因?yàn)楫?dāng)沒有人注入它時(shí),該服務(wù)就可以被搖樹優(yōu)化掉。如果沒辦法指定哪個(gè)模塊該提供這個(gè)服務(wù),你也可以在那個(gè)模塊中為該服務(wù)聲明一個(gè)提供者:

Path:"src/app/user.module.ts" 。

import { NgModule } from '@angular/core';


import { UserService } from './user.service';


@NgModule({
  providers: [UserService],
})
export class UserModule {
}

使用惰性加載模塊限制提供者的作用域

在 CLI 生成的基本應(yīng)用中,模塊是急性加載的,這意味著它們都是由本應(yīng)用啟動(dòng)的,Angular 會(huì)使用一個(gè)依賴注入體系來讓一切服務(wù)都在模塊間有效。對(duì)于急性加載式應(yīng)用,應(yīng)用中的根注入器會(huì)讓所有服務(wù)提供者都對(duì)整個(gè)應(yīng)用有效。

當(dāng)使用惰性加載時(shí),這種行為需要進(jìn)行改變。惰性加載就是只有當(dāng)需要時(shí)才加載模塊,比如路由中。它們沒辦法像急性加載模塊那樣進(jìn)行加載。這意味著,在它們的 providers 數(shù)組中列出的服務(wù)都是不可用的,因?yàn)楦⑷肫鞑⒉恢肋@些模塊。

當(dāng) Angular 的路由器惰性加載一個(gè)模塊時(shí),它會(huì)創(chuàng)建一個(gè)新的注入器。這個(gè)注入器是應(yīng)用的根注入器的一個(gè)子注入器。想象一棵注入器樹,它有唯一的根注入器,而每一個(gè)惰性加載模塊都有一個(gè)自己的子注入器。路由器會(huì)把根注入器中的所有提供者添加到子注入器中。如果路由器在惰性加載時(shí)創(chuàng)建組件,Angular 會(huì)更傾向于使用從這些提供者中創(chuàng)建的服務(wù)實(shí)例,而不是來自應(yīng)用的根注入器的服務(wù)實(shí)例。

任何在惰性加載模塊的上下文中創(chuàng)建的組件(比如路由導(dǎo)航),都會(huì)獲取該服務(wù)的局部實(shí)例,而不是應(yīng)用的根注入器中的實(shí)例。而外部模塊中的組件,仍然會(huì)收到來自于應(yīng)用的根注入器創(chuàng)建的實(shí)例。

雖然你可以使用惰性加載模塊來提供實(shí)例,但不是所有的服務(wù)都能惰性加載。比如,像路由之類的模塊只能在根模塊中使用。路由器需要使用瀏覽器中的全局對(duì)象 location 進(jìn)行工作。

使用組件限定服務(wù)提供者的作用域

另一種限定提供者作用域的方式是把要限定的服務(wù)添加到組件的 providers 數(shù)組中。組件中的提供者和 NgModule 中的提供者是彼此獨(dú)立的。 當(dāng)你要急性加載一個(gè)自帶了全部所需服務(wù)的模塊時(shí),這種方式是有幫助的。 在組件中提供服務(wù),會(huì)限定該服務(wù)只能在該組件及其子組件中有效,而同一模塊中的其它組件不能訪問它。

Path:"src/app/app.component.ts" 。

@Component({
/* . . . */
  providers: [UserService]
})

在模塊中提供服務(wù)還是在組件中

通常,要在根模塊中提供整個(gè)應(yīng)用都需要的服務(wù),在惰性加載模塊中提供限定范圍的服務(wù)。

路由器工作在根級(jí),所以如果你把服務(wù)提供者放進(jìn)組件(即使是 AppComponent)中,那些依賴于路由器的惰性加載模塊,將無法看到它們。

當(dāng)你必須把一個(gè)服務(wù)實(shí)例的作用域限定到組件及其組件樹中時(shí),可以使用組件注冊一個(gè)服務(wù)提供者。 比如,用戶編輯組件 UserEditorComponent,它需要一個(gè)緩存 UserService 實(shí)例,那就應(yīng)該把 UserService 注冊進(jìn) UserEditorComponent 中。 然后,每個(gè) UserEditorComponent 的實(shí)例都會(huì)獲取它自己的緩存服務(wù)實(shí)例。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)