欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

angular 服务providers 有大用 有大大用

Angular中有很多方式可以将服务类注册到注入器中:

  • @Injectable 元数据中的providedIn属性

  • @NgModule 元数据中的 providers属性

  • @Component 元数据中的 providers属性

创建一个文件名叫名 hero.service.ts叫 hero 的服务
 hero.service.ts            

  1. import { Injectable } from '@angular/core';
  2. @Injectable({
  3. providedIn: 'root',
  4. })
  5. export class HeroService {
  6. constructor() { }
  7. // 新增加setName方法                        
  8. setName(name:string):string{
  9. return `姓名:${name}`;
  10. }
  11. }
           
           

1.@Injectable 元数据中的providedIn属性            

providedIn: 'root' 告诉 Angular在根注入器中注册这个服务,这也是使用CLI生成服务时默认的方式.
这种方式注册,不需要再@NgModule装饰器中写providers,而且在代码编译打包时,可以执行摇树优化,会移除所有没在应用中使用过的服务。推荐使用此种方式注册服务

使用providedIn的话,后面直接在项目中使用了。            

使用:heroes.component.ts

  1. import { Component, OnInit } from '@angular/core';
  2. import { HeroService } from '../hero.service'                        
  3. @Component({
  4. selector: 'app-heroes',
  5. templateUrl: './heroes.component.html',
  6. styleUrls: ['./heroes.component.css']
  7. })
  8. export class HeroesComponent implements OnInit {
  9. constructor(private heroService:HeroService) { }
  10. ngOnInit() {
  11. this.heroService.setName('张三');
  12. }
  13. }
           

2.@NgModule 元数据中的 providers属性            

改写 hero.service.ts里面的@Injectable,如下            

  1. import { Injectable } from '@angular/core';
  2. @Injectable() // 删掉了 {providedIn: 'root'}
  3. export class HeroService {...}
           

 xx.module.ts , 例如app.module.ts

  1. ...
  2. @NgModule({
  3. providers: [
  4. HeroService,
  5. // { provide: HeroService, useValue: HeroService }
  6. ],
  7. })
  8. ...
           

然后就可以再使用啦,使用方法,同1 heroes.component.ts文件            

3.@Component 元数据中的 providers属性            

 hero.service.ts里面的@Injectable,删掉 {providedIn: 'root'},同2 hero.service.ts文件            

改写heroes.component.ts

  1. import { Component, OnInit } from '@angular/core';
  2. import { HeroService } from '../hero.service'                        
  3. @Component({
  4. selector: 'app-heroes',
  5. templateUrl: './heroes.component.html',
  6. styleUrls: ['./heroes.component.css'],
  7. providers: [HeroService] // 新增 providers: [HeroService]                        
  8. })
  9. export class HeroesComponent implements OnInit {
  10. constructor(private heroService:HeroService) { }
  11. ngOnInit() {
  12. this.heroService.setName('张三');
  13. }
  14. }
           

 

三种用法总结:

@Injectable 元数据中的providedIn属性  

  1. //service.ts                        
  2. @Injectable({providedIn:'root'})
           

@NgModule 元数据中的 providers属性

  1. // service.ts                        
  2. @Injectable()
  3. //module.ts                        
  4. @NgModule({
  5. providers: [HeroService ]
  6. })
           

@Component 元数据中的 providers属性

  1. // service.ts                        
  2. @Injectable()
  3. // component.ts                        
  4. @Component({
  5. ...
  6. selector: 'app-heroes',
  7. providers: [ HeroService ]
  8. })
           

 来自  https://blog.csdn.net/sllailcp/article/details/102548144            


           

Angular框架中的Provider依赖注入(DI)


           

依赖注入是Angular的核心,在设计应用的时候会使用到,它可以帮助我们提高开发效率和模块化程度,DI是一种编码模式,其中的类会从外部源中请求获取依赖,而不需要我们去创建它们,Angular系统中通过在类上添加@Injectable装饰器来告诉系统这个类(服务)是可注入的。

1、使用Provider来描述与Token关联的依赖对象的创建方式

Angular中依赖对象的创建方式共用4种:

  • 1、useClass

  • 2、useValue

  • 3、useExisting

  • 4、useFactory

1.1、useClass:
import {NgModule, APP_INITIALIZER, Injectable} from '@angular/core';
import {BrowserModule, HammerGestureConfig, HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
...

@Injectable()
export class ApiService {
    constructor(
      public http: Http
    )      
}

@NgModule({
    declarations: [AppComponent],
    entryComponents: [],
    imports: [
        BrowserModule,
        ....
    ],
    providers: [
        ....
        { provide: RouteReuseStrategy, useClass: ApiService }
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}

           
1.2、useValue:
  { provide: 'API_URL', useValue: 'http://api.com/v2' }
           
1.3、useExisting:
  { provide: 'ApiServiceAlias', useExisting: ApiService }
           
1.3、useFactory:
export function configFactory(config: AppConfig) {
  return () => config.load();
}

@NgModule({
  ...
  providers: [
       { provide: APP_INITIALIZER, useFactory: configFactory, 
        deps: [AppConfig], multi: true }
  ]
})
export class CoreModule { }

           
2、使用Provide

使用Provide需要首先创建Token,Token的作用是用来标识依赖对象,Token值可能是Type、InjectionToken类的实例或者字符串。推荐使用InjectionToken.
然后根据实际的需求选择依赖对象的创建方式,如:useClass、useValue、useExisting、useFactory等方式。
接着在NgModule或者是Component中去注册providers
最后使用构造注入的方式,注入与Token关联的依赖对象。

/**
* 封装Http服务,如在每个Http的请求头中添加token
*/
@Injectable() 
export class ApiService {
   constructor(
   // 调用Http服务后,返回Observable对象
      public http: Http) { 
   }
   ...
}

@NgModule({
  ...
  providers: [
       { provide: ApiService, useClass: ApiService } 
  ]
})
export class AppModule { }
           

组件页面中去调起:

export class HomePage {
  constructor(
    public apiService: ApiService // 使用构造注入的方式,注入ApiService的实例对象
  ) { }
  
  ngOnInit(): void {
    this.apiService.get(url) 
    .map(res => res.json()) // 返回的res对象是Response类型的实例
    .subscribe(result => {
      ...
    })
  }
}
           

当DI系统解析Providers时,都会对提供的每个provider进行规范化处理,也就是转换成标准的形式。

function _normalizeProviders(providers: Provider[], res: Provider[]): Provider[] {
  providers.forEach(b => {
    if (b instanceof Type) { // 支持简洁的语法,转换为标准格式
      res.push({provide: b, useClass: b});
    } else if (b && typeof b == 'object' && (b as any).provide !== undefined) {
      res.push(b as NormalizedProvider);
    } else if (b instanceof Array) {
      _normalizeProviders(b, res); // 如果是数组,进行递归处理
    } else {
      throw invalidProviderError(b);
    }
  });
  return res;
}

           

(参考了网上一些angular的资料)


           

来自  https://www.jianshu.com/p/bd230bf63aa0  

普通分类: