嗯,但是在 javascript 中

2024-03-14

我要成为大卫·诺伦的粉丝了嗡图书馆 https://github.com/swannodette/om.

我想在我们的团队中构建一个不太大的 Web 应用程序,但我无法真正说服我的队友切换到 ClojureScript。

有没有一种方法可以使用 om 中使用的原理,但用 JavaScript 构建应用程序?

我在想这样的事情:

  1. 不可变的js https://github.com/facebook/immutable-js or mori https://github.com/swannodette/mori对于不可变的数据结构
  2. js-csp https://github.com/ubolonton/js-csp for CSP
  3. 只是应用程序状态原子的普通 JavaScript 对象
  4. 不可变的js https://github.com/facebook/immutable-js对于光标
  5. 用于跟踪应用程序状态并根据光标发送通知的东西

我正在为上面的第 5 点而苦苦挣扎。

有人涉足这个领域或者有什么建议吗?也许有人尝试过使用 immutable-js 构建一个react.js应用程序?


2015年7月编辑:目前最有前途的基于不变性的框架是Redux https://github.com/gaearon/redux!看一看!它不像 Om 那样使用游标(Om Next 也不使用游标)。

游标并不是真正可扩展的,尽管使用了下面描述的 CQRS 原理,但它仍然在组件中创建了太多的样板文件,这很难维护,并且当您想要在现有应用程序中移动组件时会增加摩擦。

此外,许多开发人员并不清楚何时使用和不使用游标,而且我看到开发人员在不应该使用的地方使用游标,这使得组件的可重用性低于采用简单道具的组件。

Redux 的用途connect(),并清楚地解释何时使用它(容器组件),何时不使用(无状态/可重用组件)。它解决了将光标沿着树向下传递的样板问题,并且在没有太多妥协的情况下表现出色。

我写过关于不使用的缺点connect() here https://github.com/reactjs/redux/issues/1176#issuecomment-167087348

尽管不再使用光标,我的答案的大部分内容仍然有效恕我直言


我自己在我们的启动内部框架中完成了原子反应 https://github.com/stample/atom-react

JS 中的一些替代方案是Morearty https://github.com/Tvaroh/moreartyjs, 反应光标 https://github.com/dustingetz/react-cursor, 无所不知 https://github.com/omniscientjs/omniscient or Baobab https://github.com/Yomguithereal/baobab

那时没有immutable-js但我没有进行迁移,仍然使用普通的 JS 对象(冻结)。

我不认为真正需要使用持久数据结构库,除非您有经常修改/复制的非常大的列表。当您注意到性能问题时,您可以使用这些项目作为优化,但似乎不需要实现 Om 的概念来利用shouldComponentUpdate。一件有趣的事情是immutable-js关于批量突变。但无论如何,我仍然认为这是优化,并不是使用 Om 概念的 React 获得非常不错的性能的核心先决条件。

您可以在这里找到我们的开源代码:

它具有 Clojurescript 的概念Atom https://github.com/stample/atom-react/blob/master/src/atom/atom.js这是对不可变对象的可交换引用(用深度冻结 https://github.com/stample/atom-react/blob/master/src/utils/deepFreeze.js)。它还具有事务的概念,以防您希望原子地更新状态的多个部分。并且你可以监听 Atom 的变化(事务结束)来触发 React 渲染。

它的概念是cursor https://github.com/stample/atom-react/blob/master/src/atom/atomCursor.js,如 Om(如功能性镜片)。它允许组件能够呈现状态,而且还可以轻松修改状态。这对于表单来说很方便,因为您可以直接链接到游标以进行 2 路数据绑定:

<input type="text" valueLink={this.linkCursor(myCursor)}/>

它的概念是纯渲染,开箱即用优化 https://github.com/stample/atom-react/blob/master/src/atomReact.js#L44,就像在 Om 中一样


与OM的区别:

  • 无本地状态(禁止 this.setState(o))

在 Atom-React 组件中,您不能拥有本地组件状态。所有状态都存储在 React 之外。除非您有现有 Js 库的集成需求(您仍然可以使用常规 React 类),否则您将所有状态存储在 Atom 中(即使对于异步/加载值),并且整个应用程序会从主 React 组件重新渲染自身。 React 只是一个非常高效的模板引擎,它将 JSON 状态转换为 DOM。我发现这非常方便,因为我可以在每个渲染上记录当前的 Atom 状态,然后调试渲染代码非常容易。感谢开箱即用shouldComponentUpdate它足够快,每当用户在文本输入上按下新的键盘键或用鼠标悬停按钮时,我什至可以重新渲染完整的应用程序。即使在手机上!

  • 管理状态的自以为方法(受到 CQRS/EventSourcing 和 Flux 的启发)

Atom-React 有一种非常固执己见的方式来管理状态,其灵感来自Flux and CQRS。一旦您拥有 React 之外的所有状态,并且您有一种有效的方法将该 JSON 状态转换为 DOM,您会发现剩下的困难是管理您的 JSON 状态。

其中遇到的一些困难是:

  1. 如何处理异步值
  2. 如何处理需要 DOM 更改的视觉效果(例如鼠标悬停或焦点)
  3. 如何组织你的状态以便在大型团队中扩展
  4. 在哪里触发 ajax 请求。 https://stackoverflow.com/questions/26632415/where-should-ajax-request-be-made-in-flux-app/26633455#26633455

所以我最终提出了 Store 的概念,灵感来自于Facebook Flux 架构 https://facebook.github.io/flux/。 关键是我真的不喜欢 Flux 存储实际上可以依赖于另一个存储,需要通过复杂的调度程序来编排操作。最终您必须了解多个商店的状态才能渲染它们。

在 Atom-React 中,Store 只是 Atom 保存的状态中的一个“保留的命名空间”。

因此,我更喜欢从应用程序中发生的事件流更新所有商店。每个存储都是独立的,并且不会访问其他存储的数据(就像在 CQRS 架构中一样,其中组件接收完全相同的事件,托管在不同的计算机中,并按照自己的意愿管理自己的状态)。这使得维护变得更容易,因为当您开发新组件时,您只需了解一个存储的状态。这在某种程度上会导致数据重复,因为现在在某些情况下多个商店可能必须保留相同的数据(例如,在 SPA 上,您可能希望在应用程序的许多地方使用当前用户 ID)。但是,如果 2 个存储将同一个对象置于其状态(来自事件),这实际上不会消耗任何额外的数据,因为这仍然是 1 个对象,在 2 个不同的存储中引用了两次。

要了解这一选择背后的原因,您可以阅读 CQRS 领导者 Udi Dahan 的博客文章,重用的谬误 http://www.udidahan.com/2009/06/07/the-fallacy-of-reuse/以及其他有关自主组件的内容。

因此,存储只是一段接收事件并更新其在 Atom 中的命名空间状态的代码。

这将状态管理的复杂性转移到了另一层。现在最难的是精确定义哪些是您的应用程序事件。


请注意,这个项目仍然非常不稳定并且没有文档记录/没有经过充分测试。但我们已经在这里使用它并取得了巨大成功。如果您想讨论或贡献,可以在 IRC 上联系我:Sebastien-L in #reactjs.

这就是用这个框架开发SPA的感觉。每次在调试模式下渲染它时,您都可以:

  • 将 JSON 转换为虚拟 DOM 并将其应用到真实 DOM 所需的时间。
  • 记录的状态可帮助您调试应用程序
  • 浪费时间感谢React.addons.Perf
  • 与之前状态相比的路径差异,可以轻松了解发生了什么变化

检查这个截图:

这种框架可以带来的一些优点我还没有探索得太多:

  • 您确实内置了撤消/重做(这在我的实际生产应用程序中开箱即用,而不仅仅是 TodoMVC)。然而,恕我直言,许多应用程序中的大多数操作实际上都会对服务器产生副作用,因此将 UI 反转到之前的状态并不总是有意义,因为之前的状态已经过时了

  • 您可以记录状态快照,并将其加载到另一个浏览器中。 CircleCI 已经在行动中展示了这一点这个视频 http://blog.circleci.com/local-state-global-concerns/

  • 您可以以 JSON 格式录制用户会话的“视频”,将其发送到后端服务器进行调试或重播视频。您可以将用户会话实时流式传输到另一个浏览器以获取用户帮助(或进行监视以检查用户的实时 UX 行为)。发送状态可能非常昂贵,但像 Avro 这样的格式可能会有所帮助。或者,如果您的应用程序事件流是可序列化的,您可以简单地流式传输这些事件。我已经在框架中轻松实现了这一点,并且它可以在我的生产应用程序中运行(只是为了好玩,它还没有向后端传输任何内容)

  • 可以像 ELM 一样进行时间旅行调试

我做了“以 JSON 格式记录用户会话”功能的视频 https://www.youtube.com/watch?v=zxN8FYYBcrI对于那些有兴趣的人。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嗯,但是在 javascript 中 的相关文章

随机推荐

  • jQuery.each() 如何处理关联数组(对象)?

    我有一个关联数组 里面有两个对象 运行这个 myassoc each 回调仅运行一次 回调参数 索引和对象 也分别返回 0 和整个关联数组 人们会期望jQuery each 对数组中的每个元素运行 返回正确的键作为索引 返回正确的元素作为对
  • 替换 PhotoSwipe 库中的图像

    我有一个照片滑动 http www photoswipe com 我的页面上的画廊是这样以编程方式创建的 var instance window Code PhotoSwipe attach image options 现在我想更新图库中的
  • 在 Django 单元测试中使用会话对象

    我正在编写一个登录视图 并想为该视图添加单元测试 我的观点是这样的 def login request if request POST usrname request POST get username password request P
  • NLog - 删除超过 X 天的日志

    如何删除日志早于 X 天的文件 这很简单 但我在一个文件夹中只记录一天的日志 我的 NLog config 如下所示
  • Gnuplot 列堆叠直方图 - 行/行计数

    我有一个数据文件 其中包含未定义数量的条目 如下所示 A B C D E 1 0 2 5 4 7 4 3 4 1 8 7 4 0 7 1 1 第一行代表工作时间 然后以交替的方式暂停等等 为了可视化这一点 我通过定义两种具有不同颜色的线条样
  • 打印 char 的十进制值

    打印字符的十进制值的程序 include
  • Microsoft.Azure.NotificationHubs 1.0.9 是否与 .NET Core 2.0 兼容?

    我们将NotificationHubs 1 0 9 版与 NetCore 2 0 和 Net Framework 4 7 结合使用 在编译时 我们收到此警告 包 Microsoft Azure NOtificationHubs 1 0 9
  • 在角度4中为不同页面设置不同布局的最佳方法

    我是 Angular 4 的新手 我想要实现的是为应用程序中的不同页面设置不同的布局页眉和页脚 我有三种不同的情况 登录 注册页面 无页眉 无页脚 路线 登录 注册 营销网站页面 这是根路径 它有页眉和页脚 这些部分大多在登录之前出现 路线
  • Java/Wicket:使用资源编译基本的 Hello World

    我正在关注这个 Hello World Wicket 应用程序的示例 https www ibm com developerworks web library wa aj wicket https www ibm com developer
  • JNI - 在 Java 和 Native 代码之间传递大量数据

    我正在努力实现以下目标 1 我在java端有一个代表图像的字节数组 2 我需要让我的本机代码访问它 3 本机代码使用 GraphicsMagick 解码该图像 并通过调用 resize 创建一堆缩略图 它还计算图像的感知哈希 该哈希可以是向
  • Java Web 应用程序中的唯一序列号

    我一直想知道生成唯一 ID 的正确做法是什么 事情是在我的网络应用程序中 我将有一个插件系统 当用户注册一个插件时 我想为其生成一个唯一的序列号 我一直在考虑将所有数字存储在服 务器上的数据库或文件中 生成随机数并检查它是否已存在于数据库
  • 控制 make 的详细程度

    我正在使用 makefile 来编译由许多组成的程序 c文件 并且任何时间make被调用时 它仅编译上次运行后修改的那些文件 直到这里没有什么特别的 为了避免屏幕混乱 我在前面添加了 在每个的开头 CC 打电话 在它之前我打印一个定制的ec
  • Magento 2 设计主题选项卡丢失

    你好 我正在尝试 magento 2 并努力安装新主题 因为设计主题未显示在 商店 gt 配置 gt 设计 下 它已移至内容 设计 配置
  • 在实际设备中安装.apk文件仅用于测试

    我想在实际设备上测试我的应用程序 那么我该如何进行呢 它是附件吗sign in并使用zipalign为此目的 或者它们在准备发布我的申请时有用吗 有没有办法在不使用 eclipse 的情况下在实际设备上测试我的应用程序 下载并安装安卓软件开
  • Spring-mvc-jpa 与 Maven 错误创建 bean

    这是我的第一个问题 我是 Spring MVC 和 Jpa 的新手 我遇到了这个麻烦 我自己无法弄清楚 我尝试在 Google 上搜索 但没有找到与此错误相关的内容 我已将所有配置文件存储在 src main resources META
  • 在 Android 布局中对齐左右边缘的文本视图

    我正在开始使用Android 我无法进行简单的布局 我想用一个LinearLayout到位置二TextViews在单行中 一TextView一个在左侧 另一个在右侧 类似于 CSS 中的 float left float right 这可能
  • Typescript 属性装饰器可以为类设置元数据吗?

    在打字稿中 是否可以使用属性装饰器来设置类的元数据 考虑下面的代码 类装饰器的 目标 显然与属性装饰器的 目标 不同 我可以从另一个派生出一个吗 import reflect metadata const MY CLASS DECORATO
  • 将 int 位转换为 float 位

    我正在创建一个缓冲区 该缓冲区将在横幅中读 写 在其中我可以完全消除 TCP 分段带来的问题 我遇到的唯一问题是浮点变量 除了浮点之外 其他一切都工作正常 我找不到任何有关如何将 int32 位转换为浮点数的信息 将 float 转换为 i
  • 泛型语法:类与原始数据类型

    为什么这个不起作用 ArrayList
  • 嗯,但是在 javascript 中

    我要成为大卫 诺伦的粉丝了嗡图书馆 https github com swannodette om 我想在我们的团队中构建一个不太大的 Web 应用程序 但我无法真正说服我的队友切换到 ClojureScript 有没有一种方法可以使用 o