在依赖注入和依赖查找的时候注入器和提供器就需要使用。接下来就简单介绍一下注入器和提供器。
注入器
Angular提供的类,一般不需调用,会自动通过组件的构造函数注入。
1.当一个提供器提供在模块中时,他是对所有组件是可见的,所有组件都可以注入
2.当一个提供器提供在组件中时,他只对声明它的组件及其子组件是可见的,其他组件不可以注入
语法如下:constructor(private productService: ProductService){…}
提供器
1.当声明在模块中的提供器和声明在组件中的提供器具有相同的token时,声明在组件的提供器会覆盖声明在模块中的提供器
2.服务提供器优先声明在模块中,只有服务必须在某个组件可见,对其他组件不可见时才声明在组件中
为了让注入器明白,需要被注入的对象如何实例化。一般写在AppModule中的providers中,特殊情况写在组件@Component注解中//AppModule 中的写法
@NgModule({
providers:[ProductService]
//等价于
//providers:[{provide:ProductService,useClass:ProductService}]
})
export class AppModule { }
//组件中的写法
@Component({
selector: 'app-stock',
templateUrl: './stock.component.html',
styleUrls: ['./stock.component.css'],
providers:[{provide:ProductService,useClass:ProductService}]
})
依赖注入demo
假设,通过不同的服务方法展示不同的股票信息
思路如下
- 新建组件stock和服务stock.service.ts,使用依赖注入显示股票信息1
- 新建新的服务stock2.service.ts,显示股票信息2
新建组件stock和服务stock.service.ts//stock.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class StockService {
constructor() { }
getStock():Stock{
return new Stock(1,'NBM');
}
}
export class Stock{
constructor(public id:number,public name:string){}
}//stock.component.ts
import { Component, OnInit } from '@angular/core';
import { StockService,Stock } from '../shared/stock.service';
@Component({
selector: 'app-stock',
templateUrl: './stock.component.html',
styleUrls: ['./stock.component.css']
})
export class StockComponent implements OnInit {
stock:Stock;
constructor(public stockService:StockService) { }
ngOnInit() {
this.stock = this.stockService.getStock();
}
}//app.module.ts
providers: [StockService]
当使用服务2时,只需在stock.component中构造函数注入服务2即可。import { Injectable } from '@angular/core';
import {StockService,Stock} from './stock.service';
@Injectable()
export class Stock2Service implements StockService {
constructor() { }
getStock():Stock{
return new Stock(2,'software');
}
}import { Component, OnInit } from '@angular/core';
import { Stock2Service } from '../shared/stock2.service';
@Component({
selector: 'app-stock',
templateUrl: './stock.component.html',
styleUrls: ['./stock.component.css']
})
export class StockComponent implements OnInit {
stock:Stock;
constructor(public stockService:Stock2Service) { }
ngOnInit() {
this.stock = this.stockService.getStock();
}
}//app.module.ts
providers: [StockService,Stock2Service]
Tips:新建服务的命令行写法:ng g service stock,之前使用cnpm命令,导致无法创建service 文件。解决办法是,卸载了之前的@angular/cli,改用npm install g @angular/cli 就可以了。
提供器的作用域
提供器可写在模块和组件。模块:写在AppModule的providers声明中,全局作用域,对所有组件可见
组件:写在组件@Component注解中,写在属性providers中,只对声明它的组件及其子组件可见,一般不推荐使用//写在组件的service
import { Component, OnInit } from '@angular/core';
import { Stock,StockService } from '../shared/stock.service';
import { Stock2Service } from '../shared/stock2.service';
@Component({
selector: 'app-stock2',
templateUrl: './stock2.component.html',
styleUrls: ['./stock2.component.css'],
providers:[{provide:StockService,useClass:Stock2Service}]
})
export class Stock2Component implements OnInit {
stock:Stock;
constructor(public stockService:StockService) { }
ngOnInit() {
this.stock = this.stockService.getStock();
}
}
//与写在模块中的服务相比,只是provider的写法不同,而构造函数注入的依然是同个名字的StockService,
//但组件服务的优先级>模块服务,所以构造函数中的StockService将优先使用组件中的
//providers:[{provide:StockService,useClass:Stock2Service}]
Injectable()
写Injectable(),使其构造函数可以注入其它服务,而组件中@Component装饰器,管道装饰器都是Injectable的子类。所以,简而言之——@Injectable()、@Component 等都是为了使其构造函数可注入其他服务//在StockService 服务中注入服务AnotherstockService
import { Injectable } from '@angular/core';
import { AnotherstockService } from '../shared/anotherstock.service';
@Injectable()
export class StockService {
constructor(public anotherstockService:AnotherstockService) { }
getStock():Stock{
this.anotherstockService.login('getstock');
return new Stock(1,'NBM');
}
}
export class Stock{
constructor(public id:number,public name:string){}
}//AnotherstockService 服务
import { Injectable } from '@angular/core';
@Injectable()
export class AnotherstockService {
constructor() { }
login(message:string){
console.log(message);
}
}
而stock组件注入的StockService不需任何改变就可以在页面打印console.log(message)
学习service的时候深深地掉入了cnpm的坑,查了一下应该是cnpm的资源欠缺导致,换成npm就可以了