在开始本文的讨论之前,让我们做一道选择题:以下关于@Injectable的描述,哪些是正确的?每个服务都应该添加一个@Injectable装饰器。B@Injectable装饰器应该添加到任何使用依赖注入(DI)的服务中。C如果不使用“providedIn”选项,则不需要添加@Injectable装饰器。D@Injectable装饰器与“providedIn”选项一起意味着不应将服务添加到模块的提供程序数组中。答案是B和D。Angular自带了自己的DI框架,用于Angular应用程序的设计,以增强其模块化和效率。@Injectable()是任何Angular服务定义的重要组成部分。有些人可能会选择错误答案的原因是他们误判了Angular中@Injectable装饰器和DI的关系,没有理解这个装饰器到底做了什么。添加@Injectable并不是注册服务关于DI的控制反转(IOC)容器,有两个成对的知识需要掌握。首先是令牌。要向IOC容器注册某些服务,需要令牌。令牌是用于注册任何服务的唯一标识符。第二个知识点是provider。提供程序帮助DI容器创建特定依赖项的实例。在Angular中,可以通过两种不同的方式使用令牌注册服务并将其传递给提供者。首先,可以使用特定的@NgModule注册服务。该过程是通过将服务传递给提供者数组提供者来注册服务。在下面的示例中,使用的令牌是打字稿类型MyService。这里的提供者是useClass。该提供者策略通知Angular框架可以通过new关键字启动依赖项的实例。@NgModule({...providers:[//速记语法{provide:MyService,useClass:MyService},//速记语法MyService],})第二种方式是使用@Injectable:@Injectable({providedIn:'root'})exportclassMyService{constructor(){}}这里要注意的一件事是@Injectable装饰器与向容器注册服务无关。那么@Injectable装饰器的用途是什么?MyService可以具有某些依赖项这一事实是标准的。例如,您可以使用HttpClient。import{HttpClient}from'@angular/common/http';@Injectable()exportclassMyService{constructor(privatehttpClient:HttpClient){}}让我们尝试了解当您需要获取MyService的实例时会发生什么。当Angular需要创建服务时,应该向它传递一个HttpClient实例。那么它是怎么做到的呢?首先,Angular应该知道提到了哪个依赖项。还记得你使用令牌来注册依赖项吗?出于同样的原因,您可以向Angular询问此依赖项的实例。因此Angular将查看构造函数并查看是否为令牌HttpClient请求了服务。如果使用该令牌注册了服务,Angular可以使用该令牌启动MyService并提供它创建的实例。下面是编写译后的JavaScript代码:varMyService=/**@class*/(function(){functionMyService(httpClient){this.httpClient=httpClient;}MyService=__decorate([Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"])(),__metadata("design:paramtypes",[_angular_common_http__WEBPACK_IMPORTED_MODULE_1__["HttpClient"]])],MyService);returnMyService;}());
