应用场景
当一个父组件下的不同子组件需要进行传递数据时,我们可以选择通过Angular中的service传值
需使用到的Observable简介
在RxJS中,Subject是一类特殊的Observable,它可以向多个Observer多路推送数值。普通的Observable并不具备多路推送的能力(每一个Observer都有自己独立的执行环境),而Subject可以共享一个执行环境。BehaviorSubject是Subject的一个衍生类,它将数据流中的最新值推送给接受者
- 在服务中使用订阅来向各个组件推动数据;
- 在父组件的模板中绑定属性,父子组件中的构造函数同时使用服务参数;
- 在子组件中调用服务中的推送来推送数据更改,其他子组件可以通过ngOnChanges来检查更改然后做出相应的处理。
实例1
在公共父组件的service中先定义一个BehaviorSubject
$openTabs: BehaviorSubject<Set<ITab>> = new BehaviorSubject<Set<ITab>>(new Set());[set是Angular中的构造函数]
$openTabIndex: BehaviorSubject<number> = new BehaviorSubject<number>(-1);
// 获取这个需要在不同子组件中共享的值 其中一个子组件A中需要通过subscribe来订阅这个方法获取修改后的变量
getOpenTabs(): Observable<Set<ITab>> {
return this.$openTabs.asObservable();
}
getOpenTabIndex(): Observable<number> {
return this.$openTabIndex.asObservable();
}
//另一个子组件B通过调用此方法来修改公用的变量并通过next的方式进行通知,比如工具栏上的删除按钮的调用
openTab(tab: ITab): void {
const openTabsValue = this.$openTabs.getValue();
const openTabs = Array.from(openTabsValue);
const index = openTabs.findIndex((value: ITab) => value.name === tab.name);
if (index === -1) {
openTabsValue.add(tab);
this.$openTabs.next(openTabsValue);
this.$openTabIndex.next(openTabsValue.size);
}
}
复制代码
子组件A中的调用代码
constructor(private _commonService: TestService) {
_commonService.getOpenTabIndex().subscribe((res) => {
if (res) {
//得知变量变化后,需要执行的逻辑
}
})
}
复制代码
子组件B中的调用代码
<span (click)="commonService.openTab()"></span>
复制代码
实例2(另一种类似的方式)
在公共父组件的service中先定义一个Subject
$addData: Subject<any> = new Subject(); 通过$addData去next相关的值
子组件A中的调用代码,来获取变化后的数据
constructor(private _commonService: TestService) {
_commonService.$addData.subscribe((res) => {
if (res) {
//得知变量变化后,需要执行的逻辑
}
})
}
子组件B通过调用此方法来修改公用的变量并通过next的方式进行通知
this._xxService.$addData.next(medicalData)
复制代码
总结
实例1中的方式,是保证只能在service中更改数据,然后组件只能通过订阅来获取结果,asObservable()就是保证数据只能在service中进行更改
实例2中的方式,是让变量可以在组件中进行更改,但是对于代码的维护性和统一性更建议使用实例一中的方式
不仅是service可以通过subject进行传值,也可以在组件中使用subject进行next(),在另外一个组件中通过subscribe进行获取