对于react的渲染机制其实我不是很了解的,最近在编写一个react拖拽插件的时候为此吃了一点小苦头
对于react的渲染机制其实我不是很了解的,最近在编写一个react拖拽插件的时候为此吃了一点小苦头。
我们都知道react会事先生成一个虚拟DOM,然后插入到真实节点中,如果state发生改变后,会比较需要更新的DOM节点,实现最小化的更新。
然后问题来了。我们可以发现每一个DOM节点都有一个data-reactid,(其实是我的猜测)目前的react根据这个来与state中的数据进行比对,但是利用dragula进行拖拽排序,其实是会改变真实DOM的顺序的,因此data-reactid的顺序也就改变了,重新渲染的时候,react会按照data-reactid的顺序渲染,自然而然数据渲染的顺序就乱序了。
也就是说,我们的state里有一个数组[1, 2, 3, 4],通过遍历渲染这个state,产生一个DOM列表,列表中有四个<li>
,他们对应的data-reactid是[r1, r2, r3, r4].
现在我们拖动了实际DOM的顺序,改变数组的顺序为[1, 2, 4, 3],此时data-reactid变成了[r1, r2, r4, r3].
按照预想,重新渲染的时候,四个<li>
的文本内容顺序应当与state中的数组顺序一致,但是实际情况是,react会根据data-reactid的顺序去渲染,结果就是这样:
|
|
可以来看这样一个例子
|
|
最终结果与前述相同。
react在15.0之后取消了data-reactid,但是我猜测其内部的渲染机制依然按照上面这样一种逻辑。
因此项目中如果有拖拽真实节点改变其顺序的需求,就要注意节点顺序变化的同时,要保证state按照旧的节点顺序来渲染。可以创建一个状态副本用以保存改变后的state,但是渲染节点的state不做变化。