请在 2024 年 Clojure 状态调查中分享您的想法!

欢迎!请参阅关于页面,了解更多关于如何使用本网站的信息。

+1
ClojureScript
重新标记

在热重载时是否有可能只重新渲染受影响的 app 部分呢?

Figwheel 文档只提到重新挂载整个 app(在这种情况下,您会丢失所有组件的本地状态):https://figwheel.org/docs/hot_reloading.html#re-rendering-ui-after-saving-a-file

在 shadow-cljs 文档中也没有找到相关信息。我所见过的所有应用要么在热重载时根本不会重新渲染,要么是重新挂载。

那么,比较热重载前后的 VDOM,并根据这个差异更新 DOM 的障碍是什么?或者它已经实现了吗?

尽管 Figwheel/shadow-cljs 与 React/VDOM 独立,预期它们不会实现这种行为,但也许有一些库或定义良好的方法来实现这一点?

2 个答案

+2

事实上,这并不是“重新挂载”,而只是一种更新,并不表示整个 app 的 DOM 都被替换。调用顶级 render 与更新一个组件没有区别,React 仍然像往常一样执行 diff 和 patch。


编辑
嗯,可能我应该上传一些示例仓库,但`reagent/render-component`确实为我重新渲染了整个应用。您是否有可用的参考项目,这样我就可以进行比较,找出我哪里做错了?
by
上传了最小化示例: https://github.com/fjolne/reagent-hot-reload

如果输入字段中输入了文本,然后更改了标题的文本,热重载重新渲染将清除输入。
by
编辑 by
这种情况是预期中的,因为输入的值除了DOM外,没有存储在任何地方,所以从React的角度来看,输入中没有值。

更正:它还在Reagent中发生,但与纯React的情况不同。我想这与Reagent自己对局部状态的理解有关。
by
但如果它不在差异中,那么输入字段为什么会更新呢?而且使用Reagent atom来保存数据而不是DOM时也会有相同的行为。

编辑:已看到更正,谢谢深入分析 :)
+2
by

一般来说,如fulcrore-frame这样的框架关于状态和如何管理状态都有明确的规定。使用这些规定。

在工具级别上这样做将非常困难,这也是为什么figwheel和shadow-cljs都只处理代码的重载,将状态管理留给了实际的应用程序。我甚至不确定是否可以在工具级别上进行这种操作,而不完全限制你在代码中可以做什么。

by
我非常依赖于re-frame,但在某些情况下(简单的表单、下拉列表展开状态等)使用局部状态似乎比产生re-frame事件处理器/订阅更加简洁。
by
此外,正如上面提到的,React本身确实处理了这一点。那么为什么不能仅仅在预重载和后重载状态之间投放一个常规的VDOM差异呢?
by
如果你对纯JS应用相同的hot-reload方法,React本身不会有不同的处理。

导致事物“被替换”的原因是,当你通过热重载重新定义一个函数时,`(identical? old new)` 返回 false。因此,在你的例子中,`app` 和 `form` 有“新”的定义,所以 React 会替换它们。如果你只是从 REPL 中调用 `(mount!)`,则 `input` 状态不受影响并“生存”下来,因为实际的差异不会替换实际的 DOM 节点。
by
哦,没想到比较还对函数本身也做了,这解释了很多,谢谢!
...