【问题标题】:How to observe multiple object property changes with rxjs?如何使用 rxjs 观察多个对象属性的变化?
【发布时间】:2018-09-15 10:41:31
【问题描述】:

我有一个对象,我想使用 rxjs 观察其变化。该对象有多个属性,当它们中的任何一个发生变化时,我想知道哪个被更改了,它的新值是什么。我将以下简化版本的代码放在一起,但它不能按预期工作:http://jsbin.com/sidukulowi/1/edit?js,console

const store = Rx.Observable.create(function(observer) {
  let state = { userActions: {
    window: {
      leftPanelWidth: 300,
      backgroundColor: 0xffffff,
    }
  }};

  observer.next(state);

  state = { userActions: {
    window: {
      leftPanelWidth: 250,
      backgroundColor: 0xffffff,
    }
  }};

  observer.next(state);

  state = { userActions: {
    window: {
      leftPanelWidth: 250,
      backgroundColor: 0xff00ff,
    }
  }};

  observer.next(state);
});


const subscribe = store
  .map( state => state.userActions.window )
  .distinctUntilChanged( ( a, b ) => {
    return a.leftPanelWidth === b.leftPanelWidth && a.backgroundColor === b.backgroundColor
  })
  .subscribe(val => console.dir(val));

当上面的代码运行时,当窗口对象中的某些内容发生更改时,我会正确地得到更新,但是我不知道如何确定哪个属性是更改的。

我将如何修改它,以便我可以看到在第一次更改中,leftPanelWidth300 更改为 250,而在下一次更改中,backgroundColor 从更改为0xffffff0xff00ff ?

【问题讨论】:

  • 您可以使用 es6 代理设置陷阱,以便在对象发生更改时通知
  • 我不知道“使用 es6 代理设置陷阱”是什么意思。你能给我一个帮助文档或者一些示例代码来说明如何做到这一点吗?
  • 基本上代理可以帮助您设置不同类型的陷阱。陷阱本质上只是功能,当您尝试对代理对象执行某些操作(访问属性、设置属性、删除属性等)时,它们将充当中间件。下面的文章很好地解释了代理ponyfoo.com/articles/es6-proxies-in-depth
  • 我通读了那篇文章和这篇文章:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…,但我不明白如何在我的情况下使用代理。你能给我看一些示例代码吗?

标签: javascript object properties rxjs observers


【解决方案1】:

我才刚刚开始学习 RxJX Observable。所以这可能不是最简单的解决方案。

但您可以使用pairwise 代替distinctUntilChanged 来检查以前和当前的值。

例如。

const store = Rx.Observable.create(function(observer) {
  let state = { userActions: {
    window: {
      leftPanelWidth: 300,
      backgroundColor: 0xffffff,
    }
  }};
  
  observer.next(state);
  
  state = { userActions: {
    window: {
      leftPanelWidth: 250,
      backgroundColor: 0xffffff,
    }
  }};
  
  observer.next(state);
  //lets add again to make sure it only when
  //changed..
  observer.next(state); 
  
  state = { userActions: {
    window: {
      leftPanelWidth: 250,
      backgroundColor: 0xff00ff,
    }
  }};
  
  observer.next(state);
  
});


const subscribe = store
  .map(a => a.userActions.window)
  .pairwise()
  .map(([a,b]) => 
    Object.entries(a)
      .filter(([k,v]) => b[k] !== v)
      .map(([k,v]) => ({
        property: k,
        old: a[k],
        new: b[k]
      }))
  )
  .filter(a => a.length)
  .subscribe(val => console.dir(val));

console.log( '--------------Done--------------' );
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.8/Rx.min.js"></script>

【讨论】:

  • 非常好的解决方案!现在我只需要弄清楚如何处理第一个调用,因为pairwise只会在第二个下一个调用之后触发。也许我可以尝试执行类似 next({}) 然后 next( state ) 的操作,看看它是否会启动一个通知,说 old = undefined 和 new = initial state。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 1970-01-01
  • 2014-04-18
  • 2017-09-07
  • 2015-12-17
  • 2019-08-13
  • 2018-10-28
相关资源
最近更新 更多