【问题标题】:Flux: how to deal with objects that generate other dependent objectsFlux:如何处理生成其他依赖对象的对象
【发布时间】:2016-10-10 11:29:00
【问题描述】:

上下文:我们正在使用 React/Alt.js 构建一个复杂的 3D“模拟人生”网络应用。用户可以在 3D 场景中添加简单的对象(立方体),但更多时候他们会添加我们所谓的“预制件”,它是基于某些用户参数(长度)的几个简单对象(15 个立方体组成一个结构)的组合, 高度, ...)。

所以我们有一个包含所有简单对象的 ObjectStore,以及 PrefabStore(它只保存用户的参数来生成预制件)。

我们可以只在 React 层生成这个预制件及其对象(这样预制件渲染总是与商店中预制件的参数同步),但出于技术原因,我们需要所有这些预制件的简单对象真正存在于商店层。换句话说,我们需要在 store 中生成 prefab 的对象(ObjectStore,因为它是存储简单对象的地方)。

问题是where(在store层),when如何生成prefab及其所有依赖对象,以及我们应该在哪里存储生成的对象,知道:

  1. 当 prefab 的参数更新时,我们需要重新生成和更新对象(现有对象可以移动、旋转、完全移除)。
  2. 我们无法在 React 视图层计算预制件生成的对象,因为我们需要在存储层中生成这些对象(因为这些对象可以与其他对象交互,当我们生成包含所有现有对象的文件时也需要它们)。
  3. 生成预制件及其相关对象是一项复杂而缓慢的任务:我们不能在每次需要渲染预制件时调用此生成函数。此外,正如我在前一点中提供的那样,我们需要对生成的对象的引用,因此它们必须存在于存储中。

为了帮助理解什么是 prefab 和一个简单的object,以及为什么我们需要 prefab 的对象存在于 store 层,这里是我们应用的截图:

我的解决方案

  1. 在 React 组件中即时生成预制件和依赖对象。

优点:预制渲染和依赖对象始终与预制数据同步。当 prefab 的参数更新时,React 会自动渲染 prefab 并再次生成对象。

缺点:对象并不真正存在。它们不在 ObjectStore 中,所以我无法与它们交互(显示对象列表、生成包含所有对象的文件……)。

  1. 生成预制件和依赖对象一次,然后用生成的对象填充依赖存储(ObjectStore、PrefabStore)。

优点:所有对象都存储在自己的 Store 中。

缺点:当您更新预制件(移动/旋转/调整大小)时,很难更新所有相关生成的对象,并且您需要 ObjectStore 中的一堆存储 lsitener 以确保对象与它们所属的预制件。

  1. 即时生成预制件和相关对象,但在存储中使用记忆。 优点:依赖对象始终保持同步 + 对象确实存在于 store 层中(不确定如何在两个不同的 store 中处理这种 memoization:PrefabStore 和 ObjectStore)。

缺点:我不知道如何处理两个不同存储中的记忆:预制对象的 PrefabStore(仍然具有位置/旋转属性)和生成对象的 ObjectStore。

【问题讨论】:

  • 我不确定你对 Flux 的实现,但如果你使用 Redux(即使你不是),Reselect's memoized selectors 是一种有效处理计算数据的常见模式(特别是回答第 3 点)。无论您需要在哪里引用对象,都可以import 选择器。这使您的状态保持简单并优化计算。

标签: javascript reactjs flux


【解决方案1】:

回答这类架构问题很棘手 - 您是您自己的系统和领域的专家,但无论如何:

基本的通量规则是 Store 负责改变自己的状态以响应 Action。此外,还有良好的通用代码组织实践,如低耦合、高内聚等。

一种选择是:

  1. 某种预制模型对象,知道参数 一个预制的“模板”,并有一个生成方法来创建和返回 适当的对象(也许生成方法必须采用一些位置信息或其他东西作为参数)。预制模型可以在单独的代码模块中与任何商店分离。如果你愿意,generate 方法可以是一个纯函数,在它自己的模块中。

  2. Prefab Store 可以直接存储预制模型(可能最简单),或者只存储构建它们所需的数据。

  3. 对象存储有一个用于 ADD_FROM_PREFAB 操作的处理程序,用于查询预制存储以获取适当的预制模型数据/实例,调用 在其上生成并最终将返回的对象添加到其状态中。

  4. 然后 UI 只从 ObjectStore 渲染场景,而不是预制存储(尽管假设预制存储也用于预制库 UI?)

使用这种方法,您可以单独对预制模型和对象生成进行单元测试,并在您想要的地方轻松地重复使用它。商店代码也是相当简单的胶​​水,易于测试。并且 UI 无需担心渲染部分的预制件。

【讨论】:

  • 感谢您的回答。实际上我现在正在使用这个选项(嗯,几乎相同,请参阅我原来的帖子中的解决方案 2):我有一个预制模型,它生成所有依赖对象,然后所有依赖存储(ObjectStore)听“PREFAB_GENERATED”动作,获取生成的对象并将它们放在自己的存储中。我对这个解决方案不满意,因为当我更新我的预制件(参数、位置……)时,我需要更新所有依赖对象(完全移动/调整大小/删除),也就是重新生成我的预制件。如何确保对象始终与预制参数同步?
  • 一种选择是在 ObjectStore 中保留 prefab->生成对象的索引。然后,您可以在 ObjectStore 中收听与更新预制件相关的相关操作,并且您可以选择根据更改就地更新对象而不是重新生成它们,这可能会带来重大的性能优势。处理这个问题的代码可以在预制模块中(例如,它获取对象数组并返回更新后的数组,可能就地更新)。
  • 对于 memoization 替代方案,由于您可能没有使用不可变状态,您可以在 ObjectStore 中存储对预制件的引用。当视图查询预制件的对象存储时,此时对象存储会生成对象,并将它们与预制件一起缓存(如果它是可变的,我想你需要复制它) .如果它有一个具有相同预制的对象的缓存列表,您可以重复使用它,否则将其替换为重新生成的列表。无需触发任何内容来说明您的对象存储已更新,因为这只是缓存,而不是状态更改。
猜你喜欢
  • 1970-01-01
  • 2018-08-11
  • 2021-08-04
  • 2017-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-19
相关资源
最近更新 更多