自定义实现angular中数据的状态管理,如有不妥请指正
一、先介绍一下rxjs中subject;
mport {subject}from’rxjs’
Subject 数据的订阅与分发,结合报刊的发布与订阅进行功能的模拟,subject即是observeable对象也是observer对象,subject对于后期没有数据更新时所添加的订阅者是不怎么友好的,因为不跟新数据时订阅者就不在收到返回的数值
const interval$ = interval(1000).pipe(take(10));
const subject = new Subject();
const observerA = {
next: value => console.log('Observer A get value: ' + value),
error: error => console.log('Observer A error: ' + error),
complete: () => console.log('Observer A complete!'),
};
const observerB = {
next: value => console.log('Observer B get value: ' + value),
error: error => console.log('Observer B error: ' + error),
complete: () => console.log('Observer B complete!'),
};
subject.subscribe(observerA); // 添加观察者A
interval$.subscribe(subject); // 订阅interval$对象
setTimeout(() => {
subject.subscribe(observerB); // 添加观察者B
}, 1000);
Import{BehaviorSubject}from’rxjs’;
behaviorSubject 是subject的变种,最大的区别就是 behaviorSubject是用于保存最新的数值,而不是单纯的发送事件,会将最后一次发送的值作为当前值保存在内部属性中。
const subject = new BehaviorSubject(0); //BehaviorSubject小括号0代表的是状态
const observerA = {
next: value => console.log('Observer A get value: ' + value),
error: error => console.log('Observer A error: ' + error),
complete: () => console.log('Observer A complete!'),
};
const observerB = {
next: value => console.log('Observer B get value: ' + value),
error: error => console.log('Observer B error: ' + error),
complete: () => console.log('Observer B complete!'),
};
subject.subscribe(observerA); // 添加观察者A
// interval$.subscribe(subject); // 订阅interval$对象
subject.next(1);
subject.next(2);
subject.next(3);
setTimeout(() => {
subject.subscribe(observerB); // 添加观察者B
}, 1000);
Import {ReplaySubject}from’rxjs’;
ReplaySubject 用于重复发送最近几次的值给订阅者
const subject = new ReplaySubject(2); //ReplaySubject后的2为最后两次发送的数值
const observerA = {
next: value => console.log('Observer A get value: ' + value),
error: error => console.log('Observer A error: ' + error),
complete: () => console.log('Observer A complete!'),
};
const observerB = {
next: value => console.log('Observer B get value: ' + value),
error: error => console.log('Observer B error: ' + error),
complete: () => console.log('Observer B complete!'),
};
subject.subscribe(observerA); // 添加观察者A
// interval$.subscribe(subject); // 订阅interval$对象
subject.next(1);
subject.next(2);
subject.next(3);
setTimeout(() => {
subject.subscribe(observerB); // 添加观察者B
}, 1000);
Import{AsyncSubject}from’rxjs’;
AsyncSubject他会在subject完成后才返回一个值
const subject = new AsyncSubject();
const observerA = {
next: value => console.log('Observer A get value: ' + value),
error: error => console.log('Observer A error: ' + error),
complete: () => console.log('Observer A complete!'),
};
const observerB = {
next: value => console.log('Observer B get value: ' + value),
error: error => console.log('Observer B error: ' + error),
complete: () => console.log('Observer B complete!'),
};
subject.subscribe(observerA); // 添加观察者A
// interval$.subscribe(subject); // 订阅interval$对象
subject.next(1);
subject.next(2);
subject.next(3);
subject.complete();
setTimeout(() => {
subject.subscribe(observerB); // 添加观察者B
}, 1000);
知识兔我们要实现angular的全局数据管理就需要用到 《BehaviorSubject》
二、angular服务文件
在app.module.ts中注册服务文件
import { SomeSharedService } from '@shared/window-service/window.service';
providers: [
...
SomeSharedService,
],
TS文件:service.module.ts
mport { NgModule, ModuleWithProviders } from '@angular/core';
import { SomeSharedService } from './window.service';
export { SomeSharedService };
@NgModule()
export class ServicesModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: ServicesModule,
providers: [SomeSharedService],
};
}
}
知识兔TS服务文件名:window.service.ts
dataCount3: 0,
dataSum: 0,
});
settingKey(key, sumKey) {
const globalVar = this.globalVar.getValue();
globalVar[key] -= 1;
globalVar[sumKey] -= 1;
this.globalVar.next(globalVar);
}
}
知识兔三、全局数据初始化
在全局公用组件中进行全局数据的初始化,具体怎么用看自己怎么考虑,页面刷新时数据都会重新向后台拿取数据;
ngOnInit(): void {
const source = timer(0, 30000);
const data = source.pipe(
mergeMap(val => {
return this.http.get('/admin');
}),
distinctUntilChanged(),
);
this.distinctSub = data.subscribe(res => {
this.someSharedService$.globalVar.next(res.data);
});
}
ngOnDestroy(): void {
this.distinctSub.unsubscribe();
}
因为业务需要 定时向后台请求一次数据更新,所以简单写了一下 ,如果不需要就只要放一个http请求就行了;
使用 this.someSharedService$.globalVar.next(res.data); 从全局服务SomeSharedService文件中分发文件;
四、订阅服务数据
在需要的页面订阅分发内容,且会保存最后一次的数据;
import { SomeSharedService } from '@shared/window-service/window.service';
constructor(
private someSharedService$: SomeSharedService,
) {}
...
this.someSharedService.globalVar.subscribe(res => {
if (!(this.cdr as ViewRef).destroyed) {
this.item = res;
this.cdr.detectChanges();
}
});
因为有一些数据渲染的问题 所以需要加一层判断,这就基本实现了从后台拿取数据,在多个页面进行展示;
五、实现数据修改及同步更新
import { SomeSharedService } from '@shared/window-service/window.service';
constructor(
private someSharedService$: SomeSharedService,
) {}
...
.subscribe(res => {
if (res.code !== 200) {
this.msg.error(res.message);
return;
}
this.someSharedService$.settingKey('dataCount1', 'dataSum');
})
当完成数据请求后,调用我们内部方法,就可以在本地同步实现更新数据了;
其中原理将在后期有空时更新。
subject