Om 但在 javascript 中
问题:Om 但在 javascript 中
我将成为 David Nolen 的Om 库的粉丝。
我想在我们的团队中构建一个不太大的 Web 应用程序,但我无法真正说服我的队友切换到 ClojureScript。
有没有一种方法可以使用 om 中使用的原则但在 JavaScript 中构建应用程序?
我在想类似的事情:
1.immutable-jsormori用于不可变数据结构
2.js-csp用于CSP
- 只是应用状态原子的普通 javascript 对象
4.immutable-js用于游标
- 用于跟踪应用程序状态和基于光标发送通知的东西
我正在为上面的第 5 个问题而苦苦挣扎。
有没有人冒险进入这个领域或有什么建议?也许有人尝试使用 immutable-js 构建 react.js 应用程序?
解答
2015 年 7 月编辑:目前最有前途的基于不变性的框架是Redux!看一看!它不使用像 Om 这样的游标(Om Next 也不使用游标)。
游标并不是真正可扩展的,尽管使用了下面描述的 CQRS 原则,它仍然在组件中创建了太多的样板,这很难维护,并且当你想在现有应用程序中移动组件时会增加摩擦。
此外,许多开发人员不清楚何时使用和不使用游标,我看到开发人员在不应该使用的地方使用游标,这使得组件的可重用性不如采用简单道具的组件。
Redux 使用connect(),并且清楚地解释了何时使用它(容器组件),以及何时不使用它(无状态/可重用组件)。它解决了将光标向下传递树的样板问题,并且在没有太多妥协的情况下表现出色。
我在这里写过关于不使用connect()的缺点
尽管不再使用游标,但我的大部分答案仍然有效恕我直言
我自己在我们的启动内部框架中完成了 atom-react
JS 中的一些替代方案是Morearty,React-cursors,Omniscient或[Baobabzwz1080040zwz1080040zwz1080040
当时还没有immutable-js,我没有做迁移,仍然使用普通的JS对象(冻结)。
我不认为真的需要使用持久数据结构库,除非你有非常大的列表,你经常修改/复制。当您发现性能问题作为优化时,您可以使用这些项目,但似乎不需要实现 Om 的概念来利用shouldComponentUpdate。有趣的一件事是immutable-js关于批处理突变的部分。但无论如何,我仍然认为这是优化,而不是使用 Om 的概念在 React 中获得非常好的性能的核心先决条件。
您可以在这里找到我们的开源代码:
它具有 ClojurescriptAtom的概念,它是对不可变对象的可交换引用(与DeepFreeze冻结)。它还具有事务的概念,以防您希望以原子方式更新状态的多个部分。你可以监听 Atom 的变化(事务结束)来触发 React 渲染。
它有cursor的概念,就像在 Om 中一样(就像一个功能镜头)。它允许组件能够呈现状态,但也可以轻松修改它。这对于表单很方便,因为您可以直接链接到游标以进行 2 路数据绑定:
<input type="text" valueLink={this.linkCursor(myCursor)}/>
它具有纯渲染的概念,开箱即用优化,就像在 Om
与 Om 的区别:
- 没有本地状态(this.setState(o) 禁止)
在 Atom-React 组件中,您不能拥有本地组件状态。 所有状态都存储在 React 之外。除非您有现有 Js 库的集成需求(您仍然可以使用常规的 React 类),否则您将所有状态存储在 Atom 中(即使是异步/加载值),整个应用程序会从主 React 组件重新呈现自身。 React 只是一个模板引擎,非常高效,可以将 JSON 状态转换为 DOM。我觉得这很方便,因为我可以在每次渲染时记录当前的 Atom 状态,然后调试渲染代码非常容易。由于开箱即用的shouldComponentUpdate它足够快,我什至可以在用户在文本输入上按下新的键盘键或用鼠标悬停按钮时重新呈现完整的应用程序。即使在手机上!
- 管理状态的自以为是(受 CQRS/EventSourcing 和 Flux 启发)
Atom-React 有一种非常自以为是的方式来管理受 Flux 和 CQRS 启发的状态。一旦你拥有了 React 之外的所有状态,并且你有一种将 JSON 状态转换为 DOM 的有效方法,你会发现剩下的困难是管理你的 JSON 状态。
遇到的一些困难是:
1.如何处理异步值
2.如何处理需要DOM变化的视觉效果(以鼠标悬停或焦点为例)
- 如何组织你的状态,使其在一个大团队中扩展
4.在哪里触发ajax请求。
所以我最终想到了 Store 的概念,灵感来自Facebook Flux 架构。关键是我真的不喜欢 Flux 存储实际上可以依赖另一个存储,需要通过复杂的调度程序来编排操作。您最终必须了解多个商店的状态才能呈现它们。
在 Atom-React 中,Store 只是 Atom 持有的状态中的“保留命名空间”。
所以我更喜欢从应用程序中发生的事件流中更新所有商店。每个 store 都是独立的,不访问其他 store 的数据(就像在 CQRS 架构中一样,组件接收完全相同的事件,托管在不同的机器上,并按照自己的意愿管理自己的状态)。这使得维护变得更容易,因为当您开发一个新组件时,您只需要了解一个商店的状态。这会以某种方式导致数据重复,因为现在多个商店可能不得不在某些情况下保留相同的数据(例如,在 SPA 上,您可能希望在应用程序的许多地方都使用当前用户 ID)。但是,如果 2 个存储将相同的对象置于它们的状态(来自一个事件),这实际上不会消耗任何额外的数据,因为这仍然是 1 个对象,在 2 个不同的存储中引用了两次。
要了解这种选择背后的原因,您可以阅读 CQRS 领导者 Udi Dahan、The Fallacy Of ReUse和其他关于自治组件的博客文章。
因此,存储只是一段代码,它接收事件并在 Atom 中更新其命名空间状态。
这将状态管理的复杂性移到了另一层。现在最难的是精确定义哪些是您的应用程序事件。
请注意,这个项目仍然非常不稳定并且没有记录/没有经过很好的测试。但是我们已经在这里使用它并取得了巨大的成功。如果你想讨论或贡献,你可以在 IRC 上联系我:Sebastien-Lin#reactjs。
这就是用这个框架开发 SPA 的感觉。每次渲染时,使用调试模式,您都有:
-
将 JSON 转换为虚拟 DOM 并将其应用于真实 DOM 所花费的时间。
-
记录状态以帮助您调试您的应用程序
-
浪费时间感谢
React.addons.Perf -
与先前状态相比的路径差异,以便轻松了解发生了什么变化
检查此屏幕截图:

这种框架可以带来的一些我还没有探索过的优点:
-
你确实内置了撤消/重做(这在我的实际生产应用程序中开箱即用,而不仅仅是 TodoMVC)。但是恕我直言,许多应用程序中的大多数操作实际上都会在服务器上产生副作用,因此将 UI 反转到以前的状态并不总是有意义的,因为以前的状态会过时
-
您可以记录状态快照,并在另一个浏览器中加载它们。 CircleCI 已经在这个视频上展示了这一点
-
您可以以 JSON 格式记录用户会话的“视频”,将它们发送到您的后端服务器进行调试或重播视频。您可以将用户会话实时流式传输到另一个浏览器以获得用户帮助(或监视以检查用户的实时 UX 行为)。发送状态可能非常昂贵,但可能像 Avro 这样的格式可以提供帮助。或者,如果您的应用事件流是可序列化的,您可以简单地流式传输这些事件。我已经在框架中轻松实现了它,它可以在我的生产应用程序中运行(只是为了好玩,它还没有向后端传输任何东西)
-
可以像在 ELM 中一样进行时间旅行调试
我为制作了“用 JSON 记录用户会话”功能的视频,供感兴趣的人使用。
更多推荐
所有评论(0)