行为主体部分更改不会触发订阅



我正在使用Typescript 3.4.5和Angular 8。

请考虑以下接口:

// This is an interface which represents a piece of data, which will be partially updated
export interface TextBrick {
  kind: 'text';
  content: string;
}
export class TestService {
  test$ = new BehaviorSubject<TextBrick>({kind: 'text', content: 'initial'});
  get test(): TextBrick {
    return this.test$.value;
  }
  set test(v: TextBrick) {
    console.log('set', v);
    this.test$.next(v);
  }
}

这个想法是订阅test$行为主体来观察test.content的变化。

现在考虑以下测试:

test('test', () => {
  const instance = new TestService();
  // Watch subscription
  instance.test$.subscribe((v) => console.log('sub', v));
  // 1) Full replace, subscription triggered
  instance.test = {kind: 'text', content: 'fullreplace'};
  // 2) Partial replace, subscription not triggered
  instance.test.content = 'aa';
  // But the value of the BehaviorSubject was updated! WTF?!
  console.log('end', instance.test); 
});

控制台输出如下:

sub { kind: 'text', content: 'intitial' }    // Expected behavior
set { kind: 'text', content: 'fullreplace' } // Expected behavior
sub { kind: 'text', content: 'fullreplace' } // Expected behavior
end { kind: 'text', content: 'aa' }          // Sounds really weird!

当我设置instance.test.content时,"部分二传手"显然存在问题(我不知道如何命名(。我仔细阅读了关于setters的Typescript文档,但没有提到这个用例。

我的第一个假设是没有调用set test(),这是有道理的,因为当我在setter中添加控制台.log时,我看不到"部分"'aa'集。但是,如何在不触发订阅回调的情况下更新行为主体的值呢?

任何帮助或资源将不胜感激!

instance.test = {kind: 'text', content: 'fullreplace'};

此行调用 setter 函数

instance.test.content = 'aa';

此行调用 getter 函数,然后更改行为主体的内容,不应更改行为主体的内容。

获取值,

然后用新对象更新值,我们不会在响应式编程世界中改变对象。

const value = instance.test;
instance.test = { ...value, content: 'aa' };

最新更新