【问题标题】:What are providers in Angular2?Angular2 中的提供者是什么?
【发布时间】:2016-06-16 19:07:57
【问题描述】:

在 Angular2 组件配置中,providers 是我们可以指定的键之一。这些提供程序是如何定义的,它们的用途是什么?

@Component({
  ..
  providers: [..],
  ..
})

注意:

Angular2 文档正在逐渐成熟,但仍然很少。它目前将 providers 定义为:

一组依赖注入提供程序的服务, 组件需要。

这个递归定义不是很有帮助。通过示例进行更详细的解释确实会有所帮助。

【问题讨论】:

    标签: angular angular2-providers


    【解决方案1】:

    提供者通常是单例(一个实例)对象,其他对象可以通过依赖注入 (DI) 访问。

    如果您计划多次使用一个对象,例如,不同组件中的Http 服务,您可以请求该服务的同一个实例(重用它)。您可以在 DI 的帮助下提供对 DI 为您创建的同一对象的引用。

    @Component){
      ..
      providers: [Http]
    }
    

    ..而不是每次都创建新对象:

    @Component){}
    class Cmp {
      constructor() {
        // this is pseudo code, doens't work
        this.http = new Http(...options);
      }
    }
    

    这是一个近似值,但这是Dependency Injection 背后的一般思想 - 让框架处理可重用对象的创建和维护... Provider 是 Angular 对这些可重用对象(依赖项)的术语。

    【讨论】:

      【解决方案2】:

      注册注射剂

      提供者让 Angular 的 DI 知道可注入对象,并定义可注入对象(服务)的范围。

      注入器的层次结构

      Angular 的 DI 创建一个注入器树(父 > 子 > 孙 >...),它类似于您的组件和指令的结构。

      每个提供商一个实例

      提供程序由每个注入器维护。每个提供者都提供一个可注入的实例。

      提供者查找

      当组件或指令具有依赖项(构造函数参数)时,DI 开始在该组件的注入器中查找提供程序。如果它有一个,它会从这个提供者请求实例并注入它。

      如果注入器没有请求的键(类型)的提供者,则访问父注入器,直到根(引导),直到找到提供者并且可以注入其实例。 (如果未找到提供程序,则 DI 会抛出错误)。

      定义可注入实例的范围

      这样您可以定义共享服务的范围,因为 DI 从请求实例的组件开始向上查找,直到找到。

      单身与否

      您提供多少个可注入位置决定了将创建多少个实例(它们仅在实际请求时才被实例化)。

      如果您想为整个应用程序提供一个实例,请在根组件处仅提供一个可注入的一次(或使用bootstrap(AppComponent, [...]),这会导致相同的行为。

      如果您想要为每个组件 A 提供一个新实例,请将其添加到组件 A 的提供者中。

      (更新)NgModule 惰性和非惰性

      随着NgModule 模块的引入,引入了其他级别。使用非延迟加载模块注册的提供程序位于层次结构中的根组件之上。

      延迟加载的模块位于这些组件加载的组件和指令之上。

      由于提供程序在创建注入器后是只读的,因此无法将延迟加载模块中的提供程序添加到根注入器。因此,延迟加载的模块有自己的根范围。

      另见https://stackoverflow.com/a/45231440/217408

      【讨论】:

      • 一如既往地@Günter Zöchbauer 你为我澄清了。谢谢你。我总是关注你对 Angular js 查询的回答。
      【解决方案3】:

      将提供者想象成一个告诉 Angular 如何注入服务的配方。

      我们经常以这种方式声明提供者:

      providers: [AnyService]
      

      这只是一个简写:

      [new Provider(AnyService, {useClass: AnyService})]
      

      两种方法都在说:当有人需要“AnyService”时,提供类“AnyService”

      请注意,即使我在上面的示例中提供了相同的类,在另一种情况下我也可以这样做。

      [new Provider(AnyService, {useClass: AnyServiceCustom})]
      

      但在这两种情况下,构造函数都会保持不变:

      constructor( private _anyService: AnyService) {
      }
      

      为了更好地理解它,您需要了解依赖注入在 Angular 2 中是如何工作的,因为提供程序与它直接相关。

      这是每个 Angular 2 开发者的必读之书。

      https://angular.io/docs/ts/latest/guide/dependency-injection.html?The%20Provider%20class%20and%20provide%20function#!#injector-providers

      【讨论】:

        【解决方案4】:

        添加@Sasxa 字词,我想指出Adam Freeman 的Pro Angular book(第20 章(使用服务提供商)),以获得更好、更清晰、更详细的解释以及令人惊叹的示例。

        Providers 是在 Angular 第一次需要解析依赖项时创建和管理 服务对象 的类。Providers 用于注册类到一个角度模块作为服务。然后,这个服务类可以在模块中的自身创建阶段被其他组件使用。

        "服务 是提供通用功能以支持应用程序中其他构建块的对象,例如指令、组件和管道。服务的重要之处在于它们的使用方式,即通过一个称为依赖注入的过程。使用服务可以提高 Angular 应用程序的灵活性和可扩展性,但依赖注入可能是一个难以理解的话题。” (Pro Angular(第 20 章))

        实际上,服务可以通过依赖注入将对象分发为服务。

        import { Injectable } from "@angular/core";
        
        export enum LogLevel {DEBUG, INFO, ERROR}
        
            @Injectable()
            export class LogService {
              minimumLevel: LogLevel = LogLevel.INFO;
              logInfoMessage(message: string){
               this.logMessage(LogLevel.INFO, message);
              }
            }
        

        @Component({
             selector: "example",
             templateUrl: "example.component.html"
        })
        export class exampleComponent {
        
          constructor(logService: LogService) {};
          //to do impl
        }
        

        import { NgModule }      from '@angular/core';
        import { BrowserModule } from '@angular/platform-browser';
        @NgModule({
          imports:      [ BrowserModule ],
          providers:    [ LogService ],
          declarations: [ ExampleComponent],
          bootstrap:    [ AppComponent ]
        })
        export class AppModule { }
        

        【讨论】:

          【解决方案5】:

          提供者只是服务的实例。

          您可以创建一次并在任何地方使用它们,也可以创建多个实例。

          让我们了解如何在 Angular 中使用它们

          所有服务都在 Angular 中注册,但在我们实例化它们之前它们不能被使用。所以首先,我们必须实例化服务,我们通过使用提供者来做到这一点。

          有两种方法可以实例化服务。首先使用 providers 数组,第二个是使用 providedIn。

          第一种方法使用Providers数组

          要在全球范围内使用该服务,我们可以将提供程序放置在 AppModule 中。通过这样做,该服务的实例被创建并且应用程序中的所有组件或其他服务将使用相同的实例。

          import { NgModule } from '@angular/core';
          import { AppComponent } from './app.component';
          import { NewService } from './newService';
          
          @NgModule({
            declarations: [
              AppComponent
            ],
            providers: [NewService],
            bootstrap: [AppComponent]
          })
          export class AppModule { }
          

          要在任何特定组件中使用服务,我们可以将提供程序放在 ComponentModule 中。通过这样做,该服务的新实例被创建并且所有子组件将使用相同的实例(它将覆盖父实例)。

          import { Component, OnInit } from '@angular/core';
          import { NewService } from './newService';
          
          @Component({
            selector: 'app-root',
            templateUrl: './app.component.html',
            styleUrls: ['./app.component.scss'],
            providers:[NewService]
          })
          export class AppComponent implements OnInit {
            constructor(private newService: newService) { }
          
            ngOnInit() { }
          }
          

          注意:如果您将提供程序放在 AppComponent 中,则该应用程序中的所有组件都可以使用该实例,但其他服务将无权访问该实例。要让其他服务也使用同一个实例,请将其放在 AppModule 中。

          第二种方法使用providedIn

          您可以使用 Injectable 装饰器来实例化任何服务。

          import { Injectable } from '@angular/core';
          
          @Injectable({
            providedIn: 'root' | Type<any>
          })
          export class UserService {
          }
          

          如果它是 root,那么整个应用程序都可以访问该服务。这意味着 Angular 会创建该服务的单个实例,而整个应用程序使用相同的实例。

          如果只能在特定模块中访问它,我们可以通过为 providedIn

          提供模块名称来做到这一点
          @Injectable({
             providedIn: AnyModule
          })
          

          使用 Injectable 装饰器实例化服务的另一个优点是,如果该服务根本没有在该应用程序的任何地方使用,那么它就不会出现在已编译的 Angular 应用程序中。

          【讨论】:

            【解决方案6】:
            import { service_name} from '../path';
            
            @Component({
            
              selector: 'selector_name',     
              templateUrl: './html file name ',
              styleUrls: ['./css file name '],
              providers: [ ./'service_name'];
            
            })
            export class AppComponent {
            
              constructor(private Service_name: service_name) { 
                //enter code here
            }
            

            【讨论】:

              猜你喜欢
              • 2016-11-03
              • 2015-04-11
              • 2021-09-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-02-09
              • 2012-05-04
              相关资源
              最近更新 更多