React首先在内存中对整个结构进行组装,然后把这个结构转换成实际的DOM节点插入到浏览器DOM中。render执行的结果并不是真正的DOM节点,而是轻量的JS对象。React的虚拟对象使两个DOM树对比起来更快,具有批处理和高效Diff算法,找到他们的变化,计算更新DOM所需要做的最小的变更
虚拟DOM
- 用JS对象模拟DOM
- 把这个虚拟DOM对象转为真实的DOM插入到页面中
- 如果有事件修改了虚拟DOM,比较两个虚拟DOM树的差异,得到差异对象
- 把差异对象应用到真正的DOM树上
1 | // 节点类 |
diff算法
- Diff 比较两个虚拟DOM的区别(比较两个对象的区别)
- 根据两个虚拟对象的区别,创建出补丁(patch),描述改变的内容,将这个补丁用来更新页面
- 差异计算: 先序深度优先遍历
diff三种优化策略
- 比较同级的节点(同一父节点的子节点)
当发现节点已经不存在,则该节点及其子节点会被完全删除掉,不会用于进一步的比较。这样只需要对树进行一次遍历,便能完成整个DOM树的比较。对于不同层的节点,只有简单的创建和删除。
- 相同类型的节点比较:对属性进行重设实现节点的转换
1 | renderA: <div style={{color: 'red'}} /> |
- 列表节点的比较(key存在的意义)
- 添加、删除、排序
- 顺序的调整类似插入/删除
diff算法的三个维度
- Tree diff
- Component diff
- Element fiff
虚拟DOM的优缺点
- 优点
- 易用性强,使用DOM时,将把所有的XML文档信息都存于内存中,并且遍历简单,支持XPath,增强了易用性。
- 缺点
- 效率低,解析速度慢,内存占用量过高,对于大文件来说几乎不可能使用。另外效率低还表现在大量的消耗时间,因为使用DOM进行解析时,将为文档的每个element、attribute、processing-instrUCtion和comment都创建一个对象,这样在DOM机制中所运用的大量对象的创建和销毁无疑会影响其效率。