angular - 如何订阅和更新深层嵌套在 BehaviorSubject 中的单个属性?
问题描述
我需要创建一种方法来动态构建可单独订阅的可观察数据的数据存储。我正在使用BehaviorSubject
,因为生成的数据的值可能会发生变化并且需要反映。
我正在创建一个模块,用于SVG
从形状如下面的界面的数据对象生成代码。
export interface GraphicElement{
element: string;
elementId: string;
selfClosing?: boolean;
bind?: GraphicBinding; //this property is most relevant to this question
value?: string;
properties: GraphicProperties;
responsiveProperties?: ResponsiveProperties;
}
export interface GraphicBinding{
library: string;
property: string;
}
在我的模块中,我有一个svg-shell-component
封装所有代码的模块,一个将对象svg-group-component
迭代到一个生成 svg 元素并将其注入模板的模块中。GraphicElement
svg-element-component
可选bind
属性将让组件知道需要将值绑定到该元素。为了给出一个真实世界的例子来更好地说明我在做什么,我有一个product-spec-component
产品图表,其中包含不同尺寸、零件尺寸、开/闭跨度等的测量值,具体取决于产品。这product-data
是一个独立的存储,包含不同维度的所有测量值,这些测量值将用于生成在显示测量值graphic-data
的实例中应该绑定到的数据。svg-element-component
用户还可以在英寸和厘米之间切换,这将更新本示例中绑定的属性的值。
我处理这种情况的方法是使用服务文件以以下界面的形式动态生成和设置这些属性。
export interface GraphicBindingData{ [library: string] : GraphicBindingProperty; }
export interface GraphicBindingProperty{ [property:string] : string; }
所以在这个例子中,服务文件中会生成一个像这样的对象
BindingData: GraphicBindingData = {
specMeasurements:{
width: '2in',
height: '5in',
thickness: '.125in',
depth: '9in'
},
someOtherLibrary:{
somePropA: 'some value',
somePropB: 'some value'
}
}
回到GraphicBinding
接口中bind
属性的GraphicElement
接口,该library
属性将被设置为specMeasurements
,并且该property
属性将被设置为它需要绑定到的任何维度的名称。
因此binding-data-service
,我们将调用它的文件将被导入product-spec-component
以设置此数据,而graphic-element-component
将使用bind
属性中的值来订阅它需要的任何属性。我添加了另一个虚拟数据对象,因为我想展示如何可能存在其他属性对象,以进一步强调是什么让我很难弄清楚如何去应用BehaviorSubject
这种情况,所以个人图书馆或可能仅在一个图书馆中的个别财产可能会发生变化,而其他一切都保持不变。在这个例子中,product-spec-component
这不是什么大问题,但是在如何使用这个模块的其他方面,可能会有更多的对象具有更深层次的数据。
我正在考虑做下面的事情。
export interface GraphicBindingData{ [library:string] : BehaviorSubject<GraphicBindingProperty>; }
export interface GraphicBindingProperty{ [property:string] : BehaviorSubject<string>; }
在考虑了 aBehaviorSubject
通常如何被另一个变量观察到然后订阅之后,我不确定如何为每个库中的每个属性创建一个观察者。我也不确定.next()
在这种情况下必须如何使用来更新数据。我一直在尝试查找有关在 BehaviorSubjects 中使用 BehaviorSubjects 的更多信息,如果这对于我想要实现的目标来说是必要的,但找不到任何东西。有人可以帮助我了解如何塑造它,以便我可以订阅和更新各个属性而不影响其他可观察对象吗?
解决方案
我不推荐嵌套行为主题,它会使您的流消耗更加复杂,使用单个状态对象并应用一些过滤逻辑可能会更好
假设你有一个像
const myObj=new BehaviorSubject({orange:{apple:{cherry:'my cherry'},banana:'my banana'})
并且您想更新cherry(在这里重建不可变对象可能会很痛苦)
myObj.next({orange:{apple:{cherry:'my cherry updated'},banana:'my banana'})
并注意樱桃变化
myObj.pipe(pluck('orange','apple','cherry'), distinctUntilChanged())
因为每当其中一个值发生更改时,您都必须 .next() 整个对象,所以要做到这一点,您必须破坏并重新构造状态对象
const obj=myObj.value
//add a grape
myObj.next({...obj ,orange:{...obj.orange, grape:'my grape'}})
// or json stringify then json parse
const obj=JSON.parse(JSON.stringify(myObj.value))
obj.orange.grape='my grape'
myObj.next(obj)
或者,如果您不想要不变性,您可以直接设置属性
let obj=myObj.value
obj.orange.grape='my grape'
myObj.next(obj)
推荐阅读
- reactjs - 在组件上使用 .map 会导致组件返回“渲染中没有返回任何内容......”错误
- reactjs - webpack、webpack-obfuscator 和 webpack-cli 版本地狱
- jestjs - 开玩笑的测试快照因 last-modified、etag 和其他有意更改但无意义的值而失败
- python - 如何在pyqt5中使用带有嵌入式图形的matplotlib自定义样式
- spring - 会话范围 bean 的设置器在 RestController 中不起作用
- node.js - 如何保护无服务器应用程序中未经身份验证的用户访问的端点
- node.js - Heroku 后端 Node.js 和 Netlify 前端反应应用程序已被 CORS 策略阻止:
- python - python中的if语句以防止替换字母发生两次?
- android - 在同一本地网络上从计算机向手机发出 POST 请求
- azure-ad-b2c - 不记名令牌在 AAD B2C .NETCorre 中不起作用