按照传统设计理念,在组件(component)中不应该直接获取或保存数据, 组件应该聚焦于展示数据,而把数据访问的职责委托给服务(service)。
因此,服务就充当着数据访问、逻辑处理的功能。
一般来讲,service都应该设计成单例模式,注入到全局以便给各个组件提供服务;但如果某些service只给特定一个组件或几个组件提供服务,那注入到全局就没啥必要了,我们可以只在特定组件里面注入使用即可,用个形象点的比喻就是大众服务(单例)和特定服务(多个实例)。
下面看一下两种的实现。
单例服务
我们创建2个service和2个component:
ng g component components/news
ng g component components/prod
ng g service services/common //大众服务
ng g service services/spec //特定服务
common.service.ts:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root' // 如果是全局单例,可以注入到根组件
})
export class CommonService {
random:string;
constructor() {
this.random = Math.random().toFixed(2);
}
}
在服务里面,我声明了一个随机数,然后分别在两个组件中调用这个服务,如果随机数不变,那就是单例。
news.components.ts:
import { Component, OnInit } from '@angular/core';
import { CommonService } from '../../services/common.service';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.css']
})
export class NewsComponent implements OnInit {
constructor(commonService:CommonService) {
console.log(commonService.random)
}
ngOnInit(): void {
}
}
prod.components.ts:
import { Component, OnInit } from '@angular/core';
import { CommonService } from '../../services/common.service';
@Component({
selector: 'app-prod',
templateUrl: './prod.component.html',
styleUrls: ['./prod.component.css']
})
export class ProdComponent implements OnInit {
constructor(commonService:CommonService) {
console.log(commonService.random)
}
ngOnInit(): void {
}
}
这样news组件和prod组件就可以共享commonService单例服务了。
当然,service也可以在module里面注入,比如在app.module.ts中注入:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NewsComponent } from './components/news/news.component';
import { ProdComponent } from './components/prod/prod.component';
import { CommonService } from './services/common.service'
@NgModule({
declarations: [
AppComponent,
NewsComponent,
ProdComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [CommonService], //在模块中注入service
bootstrap: [AppComponent]
})
export class AppModule { }
注入root根组件或者注入app.module其实都一样,二者选其一即可。
特定服务
如果是特定服务那就容易了,只需在使用到的component内部声明即可。
spec.service.ts:
import { Injectable } from '@angular/core';
@Injectable() //这里不需声明注入到哪里
export class SpecService {
random:string;
constructor() {
this.random = Math.random().toFixed(2);
}
}
news.components.ts:
import { Component, OnInit } from '@angular/core';
import { SpecService } from '../../services/spec.service';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.css'],
providers:[SpecService] //组件内部声明service
})
export class NewsComponent implements OnInit {
constructor(specService:SpecService) {
console.log(specService.random)
}
ngOnInit(): void {
}
}
prod.components.ts:
import { Component, OnInit } from '@angular/core';
import { SpecService } from '../../services/spec.service';
@Component({
selector: 'app-prod',
templateUrl: './prod.component.html',
styleUrls: ['./prod.component.css'],
providers:[SpecService]//组件内部声明service
})
export class ProdComponent implements OnInit {
constructor(specService:SpecService) {
console.log(specService.random)
}
ngOnInit(): void {
}
}
测试发现news组件和prod组件打印的随机数不一致,说明service起了两个实例。
这里需要注意的是——服务必须指定注入地点。无论你是注入到组件也好模块也罢,必须要指定。
如上例,如果不在news组件或prod组件的修饰器@Component()里面注入,服务本身也没指定注入到root根组件,也没在app.module下注入,那就会报错,在使用服务时一定要注意哈~~
网友评论