注入器
每一个组件都有一个注入器实例,负责注入组件需要的对象。
注入器是angular提供的一个服务类。
注入器自动通过通过组件的构造函数,将注入器的对象注入进组件
constructor(private productService:ProductService){...}
Angular的注入器在看到这样一个构造函数声明的时候,他就会在整个Angular项目中需要这样一个叫ProductService的实例,找到后就会把实例注入到productService的对象里面去,然后我们直接用就可以了。
那么,怎么产生这样一个ProductService呢?我们就需要指定提供器。
提供器
我们需要通过组件或者模块的providers属性来声明ProductService
providers:[ProductService]
//等价于
//provide是token,useClass是要new的东西
providers:[{provide:ProductService,useClass:ProductService}]
//我new的东西就是AnotherProductService
providers:[{provide:ProductService,useClass:AnotherProductService}]
//我们还可以通过工厂写一些代码来实例化对象
providers:[{provide:ProductService,useFactory:()=>{...}}]
也就是说,注入器会通过查找与提供器provide 中token哪个是一样的,而通过token后的useClass来实例化一个具体的类.
DEMO
声明一个组件和服务
ng g component product1
ng g service shared/product
我们在声明一个server时会有这样的报错
这是因为我们还有没声明提供器,别急
product.service.ts
import { Injectable } from '@angular/core';
export class ProductService {
constructor() { }
//声明一个getProduct方法,返回一个Product对象
getProduct(): Product {
return new Product(0,"iPhone7",5899,"最新款苹果手机")
}
}
//定义一个用来封装商品信息的类
export class Product {
//通过构造函数来定义里面的字段
constructor(
public id: number,
public title: string,
public price: number,
public desc:string
) {}
}
然后我们写一下服务的提供器,打开app.module.ts
最后我们改写组件的逻辑,将服务注入进组件
import { Component, OnInit } from '@angular/core';
import { Product, ProductService } from '../shared/product.service';
@Component({
selector: 'app-product1',
templateUrl: './product1.component.html',
styleUrls: ['./product1.component.css']
})
//当一个提供器声明在组件中,它只对组件及其子组件可见,其他不可以注入他
export class Product1Component implements OnInit {
//在组件里面声明一个product属性来接收服务中获取到的数据
product: Product;
//在构造函数里,通过依赖注入声明我需要一个token类型是ProductService
constructor(
private productService:ProductService
) { }
ngOnInit() {
this.product = this.productService.getProduct();
}
}
我们将数组绑到页面,这个时候页面会显示
在上面这个例子里我们将提供器声明到了模块中,提供器也可以声明到组件中
我们在声明一个组件和一个服务
ng g component product2
ng g service shared/anotherProduct
antherProduct
import { Injectable } from '@angular/core';
import { ProductService, Product } from './product.service';
@Injectable({})
//实现ProductService,这意味着他会和ProductService有相同的方法
export class AnotherProductService implements ProductService {
getProduct(): Product {
return new Product(1, "iPhone8s", 12299, "最新款苹果手机")
}
constructor() { }
}
Product2.component.ts
import { Component, OnInit } from '@angular/core';
import { Product, ProductService } from '../shared/product.service';
import { AnotherProductService } from '../shared/another-product.service';
@Component({
selector: 'app-product2',
templateUrl: './product2.component.html',
styleUrls: ['./product2.component.css'],
providers: [{
provide:ProductService,useClass:AnotherProductService
}]
})
export class Product2Component implements OnInit {
//在组件里面声明一个product属性来接收服务中获取到的数据
product: Product;
//在构造函数里,通过依赖注入声明我需要一个tooken类型是ProductService
constructor(
private productService: ProductService
) { }
ngOnInit() {
this.product = this.productService.getProduct();
}
}
这样运行会得到下面的结果
下半部分的数据是从anotherProduct这个servers里获取的
提供器的作用域
当我们把服务声明在模块中时,这个服务对所有组件是可见的
当我们把服务声明在组件中时,这个服务对当前组件及子组件是可见的
在token相同的情况下,声明在模块中的要比组件优先级高
Injectable()
只有用Injectable装饰器,才能够把别的服务注入到当前服务里
服务间互相注入
声明一个服务,用来弹出信息
ng g service shared/logger
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LoggerService {
constructor() { }
log(message: string) {
console.log(message);
}
}
在app.module.ts声明掉
providers:[LoggerService]
修改product的service