虚拟DOM和真实DOM不同步

时间:2016-03-14 13:39:30

标签: jquery dom reactjs

最近,我们想在React中实现一些动画,这就是我们想要的:当发生某些事情时(从webSocket接收消息),重新排序react组件列表。在我的情况下,只有一个项目的位置在列表中将被更改。因此,首先,淡出项目从原始位置,然后淡入到正确的位置。 我的解决方案是使用JQuery删除并添加相应的项DOM,因为它很容易实现动画(淡入和淡出),同时我还更新底层数据结构(React依赖于渲染)正确期望生成React基于下次emitChange时的状态正确渲染DOM。但是即使底层数据结构正确,React也没有按预期工作,顺序仍然搞砸了 一个有趣的部分是当我检查Chrome中的react插件时,react组件的顺序是正确,但是,当我检查真正的DOM时,顺序是不正确的。显然,这两个DOM是不同步

有没有办法解决它?

另外,我读了React插件的动画部分,但是,我认为它是有限的,当我重新排序列表时,动画不适用。如果有实现这个的反应方式,我会很感激< / p>

1 个答案:

答案 0 :(得分:5)

在使用react时,我们不应该直接更改DOM 使用jQuery或使用postMessage操作DOM并不是一个好习惯,因为反应是如何工作的 React基于代码中的呈现方法构造虚拟DOM(DOM的内存中表示)。当UI状态发生变化时,再次调用render并创建一个新的虚拟DOM,将其与虚拟DOM的先前版本进行比较,然后仅在实际DOM中修改差异。计算并实现将旧DOM转换为新DOM所需的最小步骤数。修改真正的DOM是很昂贵的。

https://facebook.github.io/react/docs/reconciliation.html#motivation

所以当你使用jquery来改变DOM以及反应时,React会因为真正的DOM与它所期望的不同而感到困惑。尝试仅通过react(即render方法)修改DOM,并且不会弹出此错误。

因此,如果你真的必须直接触摸单个元素,你可以使用refs。 https://facebook.github.io/react/docs/more-about-refs.html#the-ref-string-attribute

另外,由于您正在重新排序列表,因此您应该记住有关反应如何工作的一些事项。 React在列表方面采用了一种非常天真的方法。它同时遍历两个列表,并在出现差异时生成突变。因此,在顶部插入一个元素将导致做出许多突变的反应。其中n是列表中元素的数量。

通过向元素添加名为keys的附加属性来解决此问题。列表中元素的键必须是唯一的。 React将知道仅将元素与相同的键进行比较而不是mutate。它会重新排序。 https://facebook.github.io/react/docs/reconciliation.html#problematic-case

而不是从DOM中删除元素并重新插入,您还可以通过CSS将其可见性设置为隐藏。 Document.getElementById()通过自我反应并在重新排序后将其更改回来 或者使用来自状态变化触发的反应中的css动画 或者使用查找一些反应动画库  基本上找到一种方法来修改DOM只使用react:)