2016-07-08 56 views
1

我仍然试图围绕rxjs和observables以及BehaviorSubject包裹头部。我想要做的是将BehaviorSubject和LocalStorage结合起来,以便在特定LocalStorage变量发生变化时通知所有组件。行为主题和本地存储

例如,请考虑以下情形。

  • 有两个组件Component1和Component2。

  • 这两个组件都在LocalStorage中寻找一个称为Component1和Component2的变量,它包含一种颜色并显示该颜色的正方形。

的Component1需要订阅中的localStorage和COMPONENT2 “Component1Color” 键需要订阅 “Component2Color” 在localStorage的。

执行此操作的一种方法是拥有一个BehaviorSubject,它可以维护LocalStorage的状态,并随时对任何变量进行更改,并将此消息广播给订阅了BehaviorSubject的所有组件。

这种方法的问题是,当Component2Color更新时,component1也会收到通知,并且不会执行任何操作。

最好不过的是,Component1只有在Component1Color更新时才会收到通知,而Component2只有在更新Component2Color时才会收到通知。有没有一种方法可以使用单个BehaviorSubject来完成?

+0

你使用'distinctUntilChanged()'吗?你可以发布你的代码,所以我们可以看到你在做什么? – Sasxa

+0

我只是玩rxjs,还没有工作代码呢。我试图弄清楚我应该如何创建一个LocalStorage的包装来处理上述情况。我只是看着distinctUntilChanged,它看起来正是我想要的:)我可以为每个组件传入一个比较器函数,并且只有在diff函数成功时才会触发订阅者。 –

回答

2

您可以通过StorageEvent

const storage = Rx.Observable.fromEvent(window, 'storage').groupBy(ev => ev.key); 

听存储事件然后你可以通过做访问每个流:

let component1Stream = storage.filter(x => x.key === 'Component1Color').merge(); 

//Or using flatMap 
let component2Stream = storage.flatMap(x => 
    x.key === 'Component2Color' ? x : Rx.Observable.empty() 
); 

编辑

正如指出了注释,存储事件仅用于跨页面更新,如果您处于同一页面,它不会更新。幸运的是,解决方案仍然几乎相同,您只需为localStorage对象提供装饰器对象,以便它可以发出事件。

class RxLocalStorage { 
    private _subject: Rx.Subject<any>; 
    private _updates: Observable<any>; 
    constructor() { 
    this._subject = new Rx.Subject(); 
    this._updates = this._subject.groupBy(ev => ev.key) 
     .share(); 
    } 
    getItem(key) { return this._updates.filter(x => x.key === key).merge(); } 
    setItem(key, newValue) { 
    const oldValue = localStorage.getItem(key); 
    const event = {key, newValue, oldValue}; 
    localStorage.setItem(newValue); 
    this._subject.next(event); 
    } 
} 


let myLocalStorage = new RxLocalStorage(); 
myLocalStorage.getItem('Component1Color') 
    .subscribe(x => console.log('Component1 Color changed')); 

myLocalStorage.setItem('Component1Color', 'blue'); 
//-> Component1 Color changed 

注意上述假设所有订阅的你开始进行更改之前进行。

+1

此事件仅在未激活的页面中激发。假设你有两个tab向example.com打开,如果你有这个事件集并更新'tab2'中的存储,那么'tab1'将触发事件,但不是'tab2'。 – subhaze

+0

公平点,我不知道,我会更新。 – paulpdaniels