React Diff算法

引言

React 使用的是 Virtual DOM,使得元素脱离了文档流,将 DOM 的比对转化为 JS 的比对。这种比对用到了虚拟 DOM 的 diff 算法

背景知识

重排(回流 Reflow)与重绘(Repaint)

重排(回流)是一整个浏览器变化的情况,需要重建 DOM 树
这种过程一般发生在:

  1. 首次渲染
  2. 窗口大小改变
  3. 部分元素大小位置变化
  4. 字体大小变化
  5. 增删可见 DOM 元素
  6. 激活 CSS 伪类

总的来说,要么是浏览器本身发生了大小变化,要么是其中的 DOM 元素大小变化影响到其他 DOM 元素了,这样文档流会发生变化。

关于为什么激活 CSS 伪类也会出现回流,我没有查到相关资料,欢迎大家留言

重绘则发生于一小块变化的情况,这种变化不影响其他部分的位置,比如:

  1. color
  2. background-color
  3. visibility

显然,重排比重绘代价高很多

虚拟 DOM(Virtual DOM)

从 JSX 到浏览器 DOM

JSX -> createElement 方法 -> JS 对象(虚拟 DOM) -> 真实 DOM

JSX 中的标签事实上是一种语法糖,实质是调用 React.createElement()生成一个 JS 对象

如:

<div>Hello {this.props.toWhat}</div>

生成的是

React.createElement('div', null, `Hello ${this.props.toWhat}`);

原理

由于有了虚拟 DOM 的设定,元素脱离了文档流,不再直接操作 DOM,而是将多重修改合并,再将元素带回文档中避免频繁触发回流与重绘

虚拟 DOM 的 Diff 算法

全称是 difference 算法

同级比较,若某一层两个虚拟 DOM 节点不一致,就不再往下比较了,直接将原始页面的虚拟 DOM 删除掉,替换新的。

对于 list,每一个元素都有一个单独的 key 值(一般为后台数据的唯一 id 字段,不能是 index),根据 key 值来判断更新前后的 item 是不是一样的

例:

不使用 key

原始:
(a) (b) (c) (d) (e) (f)

插入(g)到(b)(c)之间:
(a) (b) (g) (c) (d) (e) (f)

需要更新的DOM节点有:5个
(a) (b) (c) (d) (e) (f)
(a) (b) (g) (c) (d) (e) (f)
 √   √   ×   ×   ×   ×   ×

使用 key

原始:
(a:1) (b:2) (c:3) (d:4) (e:5) (f:6)

插入(g:7)到(b:2)(c:3)之间:
(a:1) (b:2) (g:7) (c:3) (d:4) (e:5) (f:6)

需要更新的DOM节点有:1个
(a:1) (b:2)       (c:3) (d:4) (e:5) (f:6)
(a:1) (b:2) (g:7) (c:3) (d:4) (e:5) (f:6)
  √     √     ×     √     √     √     √

如果使用 index 作为 key:

原始:
(a:1) (b:2) (c:3) (d:4) (e:5) (f:6)

插入(g)到(b)(c)之间:
(a:1) (b:2) (g:3) (c:4) (d:5) (e:6) (f:7)

需要更新的DOM节点有:5个
(a:1) (b:2) (c:3) (d:4) (e:5) (f:6)
(a:1) (b:2) (g:3) (c:4) (d:5) (e:6) (f:7)
  √     √     ×     ×     ×     ×     ×
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值