持久数据结构如何帮助使Om更快

时间:2015-06-08 21:10:43

标签: clojure clojurescript om

据说,React的clojurescript包装器非常快,因为它利用了不变性。我无法理解持久性数据结构如何在这里提供帮助。

我所理解的是应用状态是一个原子。此状态被传递给返回虚拟DOM节点的函数(om组件),因此创建当前虚拟DOM与其先前状态之间差异的“补丁”比直接在实际DOM上运行要好得多。

但是持久性数据结构可以在这里提供帮助吗?

(def app-state (atom {:foo {:counter 0}))
(om/root click-counter app-state {:target ...}) 

例如click-counter呈现一个按钮,单击该按钮会递增计数器。所以转换函数如下所示:

(dom/button #js {:onClick #(om/transact! app [:foo :counter] inc)} 
            (str "clicked " (-> app :foo :counter) " times"))

我没有理解这一点:当执行onClick时,clojurescript会像这样创建一个新的地图(非常有效):

{:foo {:counter 1}}

app-state现在指向新地图。在这一点上,Om意识到状态已经改变,因为它只是一次平等检查的问题。

这里的问题是Om应该仍然计算整个旧虚拟DOM和新虚拟DOM之间的差异。它不知道只是计数器被改变了。

我的错误在哪里?

1 个答案:

答案 0 :(得分:4)

当app状态存储在像地图这样的持久树结构中时,它立即明显地显示状态树的哪些部分没有改变,并且不会需要更新。这是因为对子项的任何更改都会更改父项。随着可变数据结构的变化,孩子们不必改变父母。

所以如果你的州看起来像这样:

{:part1 [1 2 3 4]
 :part2 [:a :b]}

并通过在第2部分中添加内容来创建新状态:

{:part1 [1 2 3 4]
 :part2 [:a :b :c]}

然后比较函数可以查看并看到旧状态和新状态中的值是完全相同的对象,因此不能对任何嵌套状态进行任何更改,因为它'不可改变的。