React 虚拟DOM及diff算法

来源:互联网 发布:软件开发就业岗位 编辑:程序博客网 时间:2024/06/07 05:04

虚拟DOM合理性

由于操作DOM很慢,界面性能很多都是操作DOM引起的,而操作JS很快,用JavaScript对象很容易表示DOM节点,包括标签属性子节点,即根据DOM结构递归创建虚拟DOM树,在页面状态改变需要操作DOM时,先通过虚拟DOM计算出对真实DOM的最小修改量,然后再修改真实的DOM。

  • 1.两个相同组件产生类似的结构,不同组件产生不同的DOM结构。
  • 2.对于同一层次的一组子节点,通过唯一的key值进行区分。

一、不同节点类型的比较

  • 在虚拟树中比较两个虚拟DOM节点,若两个节点类型不同,则直接销毁前面的节点,创建并插入新节点。
  • 若被删除的节点之下还有子节点,那么这些子节点也会一并删除。因为一般情况不同组件产生不同的DOM结构,与其浪费时间比较他们基本不会相等的DOM结构还不如加个新组建上去。

二、只会逐层比较节点

比如A节点下有子节点BC,要将A节点包括其子节点移动到其他节点下面,则不是将A赋值并移动到其他节点如D下面,而是重新创建每一个节点:

A.destroy();A = new A();a.append(new B());a.append(new C());D.append(A);

三、相同节点类型的比较

相同类型的节点, 对属性进行重设。

四、列表节点的比较

列表中节点若没有唯一标识的key值的话,会提示警告。
假设在列表ABCD中B的后面插入E,若没有key值则会将C更新为E,将D更新为C,最后插入D节点。
但是若有key值的话,react会找到正确的插入位置。
还有若A下面有BC子节点,若未提供key值,则react认为BC类型不同,要调整BC的位置会将BC删除后重新新建再插入,若有key值的话,则只是更新BC和其父组件而已。

diff算法

diff算法采用动态规划的方法求两个序列X和Y,长度分别为m,n,的最长公共子序列,时间复杂度为mn,比较两颗树的时间复杂度为n^3,因为树遍历复杂度为n
假设有两个序列X=(GAC),长度为m,Y=(AGCAT),长度为n,则X和Y的嘴馋公共子序列为:

这里写图片描述

最长公共子序列LCS(Xi,Yj)分析:

  • X或者Y中有一个长度为0时,其公共子序列为空;
  • XY的第i个字符相等时,其公共子序列LCS(Xi,Yj)=XiLCS(Xi-1,Yj-1);
  • XY的第i个字符不相等时,其公共子序列LCS(Xi,Yj)LCS(Xi,Yj-1)LCS(Xi-1,Yj)中最大的一个。

这里写图片描述

由于第i次构造最长公共子序列时要用到第i-1次的最长公共子序列,因此将第一次构造时的最长公共子序列设为空;
举例:

  • 最后一个格子,CT不等,因此,取LCS('GAC','AGCA')=倒数第一行倒数第二个格子LCS('GA','AGCAT')=倒数第一列倒数第二个格子的最大值,即(AC)&(GC)&(GA);

  • 第4行的A和第6列的A相等时取ALCS('G','AGC')=G.

原创粉丝点击