自定义实现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'); })
当完成数据请求、更新后,修改广播中心的数据,以后同步给接收者一份最新的数据,从而达到广播的的效果;