自定義實現angular中數據的狀態管理,若有不妥請指正javascript
1、先介紹一下rxjs中subject;vue
Subject 數據的訂閱與分發,結合報刊的發佈與訂閱進行功能的模擬,subject便是observeable對象也是observer對象,
subject對於後期沒有數據更新時所添加的訂閱者是不怎麼友好的,由於不跟新數據時訂閱者就不在收到返回的數值java
import {subject}from’rxjs’ 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實現相似vuex的全局數據管理就須要用到 BehaviorSubject廣播模式vuex
2、angular服務文件app
在app.module.ts中註冊服務文件ide
import { SomeSharedService } from '@shared/window-service/window.service';
providers: [
...
SomeSharedService,
],
TS文件:this
service.module.ts文件spa
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服務文件名:code
window.service.ts文件server
import { 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); } }
3、全局數據初始化
在全局公用組件中進行全局數據的初始化,具體怎麼用看本身怎麼考慮,頁面刷新時數據都會從新向後臺拿取數據;
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文件中分發文件;
4、訂閱服務數據
在須要的頁面訂閱分發內容,且會保存最後一次的數據;
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(); } });
// 由於有一些數據渲染的問題 因此須要加一層判斷,這就基本實現了從後臺拿取數據,在多個頁面進行展現;
5、實現數據修改及同步更新
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'); })
當完成數據請求、更新後,修改廣播中心的數據,以後同步給接收者一份最新的數據,從而達到廣播的的效果;