自定義實現angular中數據的狀態管理,如有不妥請指正
一、先介紹一下rxjs中subject;
Import {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
import { 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.tsimport { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class SomeSharedService {
public globalVar: BehaviorSubject<any> = new BehaviorSubject({
dataCount1: 0,
dataCount2: 0,
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,
) {}
...
this.http.get(xxx).
subscribe(
res
=> {
if (
res.
code !==
200) {
this.
msg.
error(
res.
message);
return;
}
this.
someSharedService$.
settingKey(
'dataCount1',
'dataSum');
})
當完成數據請求后,調用我們內部方法,就可以在本地同步實現更新數據了;
其中原理將在后期有空時更新。
subject
