dom diff算法和虚拟DOM
React中的render方法,返回一个DOM描述,结果仅仅是轻量级的js对象。Reactjs只在调用setState的时候会更新dom,而且还是先更新Virtual Dom,然后和实际DOM比较,最后再更新实际DOM。
React.js 厉害的地方并不是说它比 DOM 快(这句话本来就是错的),而是说不管你数据怎么变化,我都可以以最小的代价来更新 DOM。方法就是我在内存里面用新的数据刷新一个虚拟的 DOM 树,然后新旧 DOM 树进行比较,找出差异,再更新到真正的 DOM 树上。
当我们修改了DOM树上一些节点对应绑定的state,React会立即将它标记为“脏状态”。在事件循环的最后才重新渲染所有的脏节点。在实际的代码中,会对新旧两棵树进行一个深度优先的遍历,这样每个节点都会有一个唯一的标记,每遍历到一个节点就把该节点和新的的树进行对比。如果有差异的话就记录到一个对象里面,最后把差异应用到真正的DOM树上。 算法实现 1 步骤一:用JS对象模拟DOM树 2 步骤二:比较两棵虚拟DOM树的差异 3 步骤三:把差异应用到真正的DOM树上 这就是所谓的 diff 算法
dom diff采用的是增量更新的方式,类似于打补丁。React 需要为数据添加 key 来保证虚拟 DOM diff 算法的效率。key属性可以帮助React定位到正确的节点进行比较,从而大幅减少DOM操作次数,提高了性能。
virtual dom
,也就是虚拟节点。它通过JS的Object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM节点。
http://react-china.org/t/dom/638
- 为什么js对象模拟DOM会比js操作DOM来得快
为了解决频繁操作DOM导致Web应用效率下降的问题,React提出了“虚拟DOM”(virtual DOM)的概念。Virtual DOM是使用JavaScript对象模拟DOM的一种对象结构。DOM树中所有的信息都可以用JavaScript表述出来,例如:
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
可以用以下JavaScript对象来表示:
{
tag: 'ul',
children: [{
tag: 'li', children: ['Item 1'],
tag: 'li', children: ['Item 2'],
tag: 'li', children: ['Item 3']
}]
}
这样可以避免直接频繁地操作DOM,只需要在js对象模拟的虚拟DOM进行比对,再将更改的部分应用到真实的DOM树上
- react组件性能优化
使用PureRenderMixin、shouldComponentUpdate来避免不必要的虚拟DOM diff,在render内部优化虚拟DOM的diff速度,以及让diff结果最小化。