2024 Clojure状态调查!中分享您的想法。

欢迎!请查阅关于页面以了解更多关于此网站如何运作的信息。

+1
ClojureScript
重标记

在热重载时有办法仅重新绘制受影响的app部分吗?

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

在shadow-cljs文档中没有找到关于这一点的内容。到目前为止,我所看到的app要么在热重载时不重新绘制,要么是进行重置。

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

尽管Figwheel/shadow-cljs与React/VDOM无关,但他们不实现这样的行为也是意料之中的,但也许有一些库或明确定义的策略可以做到这一点?

2 个回答

+2

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

by
编辑了 by
好吧,我可能应该上传一些示例仓库,但`reagent/render-component`确实为我重新渲染了整个应用。也许你有一个参考项目在手,这样我就可以比较并找出我哪里做错了?
by
已上传最小复现: https://github.com/fjolne/reagent-hot-reload

如果输入字段中输入了文本,并且之后更改了标题文本,热重载后的重新渲染将清除输入。
by
编辑了 by
这种情况是预料之中的,因为输入的值只在DOM中存储,从React的角度来看,输入框中没有值。

纠正:这也在Reagent中发生,但在普通React中不会。我认为这与Reagent自己对局部状态的概念有关。
by
但如果它不在diff中,为什么还要更新输入字段呢?使用Reagent原子保存数据而不是DOM时,也是同样的行为。

编辑:看到纠正了,感谢深入探讨 :)
+2

通常,像fulcrore-frame这样的框架都有关于状态及其管理的明确定义规则。请使用这些。

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

我大量使用re-frame,但在某些情况下(简单的表单、下拉框展开状态等)似乎更简洁地使用本地状态,而不是生成re-frame事件处理程序/订阅。
此外,如上所述,React 本身确实处理这个问题。那么为什么不能只将预加载和后加载状态之间的常规VDOM差异丢弃呢?
如果你将对纯JavaScript应用相同的快速重载方法,React 本身并不对这种情况做任何不同的处理。

导致事情被“替换”的原因是 `(identical? old new)` 在您通过快速重载重新定义一个函数时返回 false。因此,在您的示例中,`app` 和 `form` 有“新”的说明,所以React用它们替换了。如果您只从REPL中调用 `(mount!)`,则“input”状态不会被触及,“存活”下来,因为实际的差异并不替换实际的DOM节点。
哦,不知道比较也是在函数本身进行的,这解释了很多,谢谢!
...