美文网首页
Angluar4的注入器与提供器

Angluar4的注入器与提供器

作者: 南蓝NL | 来源:发表于2017-11-17 22:20 被阅读0次
constructor(private ProductService:productService){...}//注入器
//提供器
providers:[productService]
providers:[{provide:productService,useClass:productService}]
providers:[{provide:productService,useClass:AnotherProductService}]
providers:[{provide:productService,useFactory:() =>{...}}]

首先我们来看一个简单的例子

一个简单依赖注入样例.png
ng g service shared/product  //创建一个服务

在创建好的项目里的shared文件里的product.service.ts写入

import { Injectable } from '@angular/core';
@Injectable() //这个装饰器的作用是决定着ProductService可以通过构造函数注入其它的服务,
             // 现在是ProductService能否注入到其它的服务中去,是由模块的提供器决定的
             //如app.modules.ts的 providers: [ProductService],
export class ProductService {
//这里是想实现服务注入到服务
  constructor() {}
   getProduct():Product{
     return new Product(0,"iphone7",5899,"最新款苹果手机")
   }
  }
  export class Product {
    constructor(
        public id:number,
        public title:string,
        public price:number,
        public desc:string
    ){}
  }

然后在product1.component.ts通过构造函数创建注入器

import { Component, OnInit } from '@angular/core';
import {Product} from "../shared/product.service";
import {ProductService} from "../shared/product.service";
@Component({
  selector: 'app-product1',
  templateUrl: './product1.component.html',
  styleUrls: ['./product1.component.css']
})
export class Product1Component implements OnInit {
   product: Product;
   constructor(private productService:ProductService) { }
  ngOnInit() {
    this.product = this.productService.getProduct();
  }
}

在然后在app.component.ts里面创建提供器

  providers: [ProductService]

接下来在product1.componet.html里面绑好数据

<div>
  <h1>商品详情</h1>
  <h2>名称:{{product.title}}</h2>
  <h2>价格:{{product.price}}</h2>
  <h2>描述:{{product.desc}}</h2>
</div>

最后在app.component.html里面注册product1组件

    <app-product1></app-product1>

提供器的作用域

上文我们是把提供器放在app.component.ts中,这次我们把提供器放在自身的组件当中,唯一的区别是把提供器放在product2.component.ts中

@Component({
  selector: 'app-product2',
  templateUrl: './product2.component.html',
  styleUrls: ['./product2.component.css'],
  providers:[{
    provide:ProductService(指定了一个token),useClass:AnotherProductService (实   例化一个对象)
  }]
})
export class Product2Component implements OnInit {
  product: Product;
  constructor(private productService:ProductService) { }
  ngOnInit() {
    this.product = this.productService.getProduct();
  }
}

关于提供器的作用域的几个注意点

  1. 提供器如果声明在app.component.ts模块中,那么它的作用域对于所有组件来说都是可见的
  2. 提供器如果声明在组件当中,那么只有它本身的组件及子组件是可见的
  3. 如果定义了相同的token,组件的token会覆盖模块的token
  4. 优先将提供器声明在模块中

服务之间的注入

新建服务命令

ng g service shared/logger

logger.service.ts

@Injectable()
export class LoggerService {
  constructor() { }
   log(message:string){
     console.log(message);
   }
}

product.service.ts

import { Injectable } from '@angular/core';
import {LoggerService} from "./logger.service"
@Injectable() /
export class ProductService {
//这里是想实现服务注入到服务
  constructor(public logger:LoggerService) {}
   getProduct(): Product{
     this.logger.log("getProduct方法被调用");
     return new Product(0,"iphone7",5899,"最新款苹果手机")
   }
  }
  export class Product {
    constructor(
        public id:number,
        public title:string,
        public price:number,
        public desc:string
    ){}
  }

在another.service.ts中这里会报一个错误,引起的原因是在构造函数的声明没有和父类保持一致


another.service.ts报错.png

解决办法是:因为another使用的是product服务,product.service.ts的构造函数声明了logger服务,another作为子类与父类保持一致,所以也要在构造函数里面进行声明

@Injectable()
export class AnotherProductService implements  ProductService{
  getProduct():Product {
    return new Product(1,"iphoneX",8888,"买不起买不起")
  }
  constructor(public logger:LoggerService) {
      }
}

使用工厂模式声明提供器

 providers: [{
    provide:ProductService,
    useFactory:() =>{
      let logger = new LoggerService();
      let dev = Math.random()>0.5;
      if(dev){
        return new ProductService(logger);
      }else{
        return new AnotherProductService(logger);
      }
    }
  },LoggerService],
  bootstrap: [AppComponent]
})

一般来说可以传值

  providers: [{
    provide:ProductService,
    useFactory:(logger:LoggerService,isDev) =>{
      if(isDev){
        return new ProductService(logger);
      }else{
        return new AnotherProductService(logger);
      }
    },
    deps:[LoggerService,"IS_DEV_ENV"]
  },LoggerService,{
     provide:"IS_DEV_ENV",useValue:false
  }],
  bootstrap: [AppComponent]
})

也可以传一个对象

  providers: [{
    provide:ProductService,
    useFactory:(logger:LoggerService,appConfig) => {
      if(appConfig.isDev){
        return new ProductService(logger);
      }else{
        return new AnotherProductService(logger);
      }
    },
    deps:[LoggerService,"APP_CONFIG"]
  },LoggerService,{
     provide:"APP_CONFIG",useValue:{isDev:false}
  }]

等下,究竟发生了什么事。让我们看看product2.component.ts中的主要代码

export class Product2Component implements OnInit {
  product: Product;
  constructor(private productService:ProductService) { }
  ngOnInit() {
    this.product = this.productService.getProduct();
  }
}

梳理下整个过程。首先在商品组件里面的构造函数里声明了productService的token来注入服务,Ng看到之后会去找ProductService对象的提供器,然这个对象是使用工厂模式来实例化的,然后又发现这个工厂需要依赖于另外一个服务,根据这个服务的提供器声明去找,直到把所有的组件都组装好,而productComponent这个组件完全是透明的,服务和组件隔离开来,让组件更好地复用。


image.png

注入器及其层次关系

注入器.及其层次关系.png

子组件会根据自己的注入器查看本身有没有注册提供器,如果没有的话,就会根据注入器的token(这里的token是一个服务)查父组件app.component.ts的注入器上是否有合适的提供器,如果还是没有,则继续往上找,找到应用层注入器,看应用级的注入器有没有合适的提供器,即使app.modules.ts。如果还是没有,则会抛出异常。还有一点,值得注意的是,Angluar只能通过构造函数来注入,其他语言中不止局限于这一种。

相关文章

  • Angluar4的注入器与提供器

    首先我们来看一个简单的例子 在创建好的项目里的shared文件里的product.service.ts写入 然后在...

  • Angluar4的注入器与提供器——实战

    需求分析,我需要从点击每个商品显示每个商品的详情页,之前使用的是通过路由传商品名称,现在是通过传商品的id,在真实...

  • angular4依赖注入

    然后用组件演示了注入器和提供器,并演示了组件内提供器和模块提供器的区别。

  • 依赖注入 提供器

    改造app 新建商品详情组件productdetail,在商品详情组件中获取商品的标题 新建一个home组件用于封...

  • 4.注入器及层级关系

    在应用启动中,会首先创建一个应用级的注入器 ,然后将模块声明的提供器都注入到这个提供器中, imports声明的模...

  • --2提供器入门补充2

    演示服务注入服务 模块声明提供器

  • Spring-DI(依赖注入)

    Spring DI依赖注入 setter设置注入(保证类中有提供setter方法) 构造器注入 命名空间注入 1、...

  • ng4.x 注入器

    在应用启动时,angular会首先创建一个应用级的注入器,然后将模块中声明的提供器都注册到这个注入器中,然后ang...

  • ARouter 提供的服务2020-12-05

    ARouter提供了两个默认的IProvider对象:拦截器和自动注入 一、 拦截器服务 1.声明 获取服务器拦截...

  • Dagger2使用(二)

    Dagger简单使用 要实现注入,至少需要@Component可以简单理解为注入器,由它将需要注入和对象实例提供连...

网友评论

      本文标题:Angluar4的注入器与提供器

      本文链接:https://www.haomeiwen.com/subject/uydsvxtx.html