前言:虚拟DOM(Virtual dom),也就是我们常说的虚拟节点,它是通过JS的Object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM的节点。
例子:
// 创建虚拟节点 var temp = document.createDocumentFragment(); for( var i=0; i<100; i++ ){ var li = document.createElement('li'); // 将li放入虚拟节点中,这一步操作不会产生重绘回流 temp.appendChild(li); li.innerHTML = i; } // 真实节点的操作 ul1.appendChild(temp);
一:react 的虚拟dom是怎么实现的
首先说说为什么要使用Virturl DOM,因为操作真实DOM的耗费的性能代价太高,所以react内部使用js实现了一套dom结构,
在每次操作在和真实dom之前,使用实现好的diff算法,对虚拟dom进行比较,递归找出有变化的dom节点,然后对其进行更新操作。
为了实现虚拟DOM,我们需要把每一种节点类型抽象成对象,每一种节点类型有自己的属性,也就是prop,每次进行diff的时候,react会先比较该节点类型,
假如节点类型不一样,那么react会直接删除该节点,然后直接创建新的节点插入到其中,假如节点类型一样,那么会比较prop是否有更新,假如有prop不一样,
那么react会判定该节点有更新,那么重渲染该节点,然后在对其子节点进行比较,一层一层往下,直到没有子节点
二:为什么要使用虚拟节点?
频繁的操作DOM,会大量的造成页面的重绘和回流,出于性能优化的考虑,我们应该减少重绘和回流的操作。
重绘:例如 div1.style.color='red' 这种代码,只能改变颜色,并不会影响其他元素的布局,这种操作被称为重绘。
回流:例如 div1.style.padding = '20px' 这种代码,会影响到其他元素的布局,这种操作被称为回流。
回流必将引起重绘,而重绘不一定会引起回流。比如:只有颜色改变的时候就只会发生重绘而不会引起回流。
对虚拟节点的DOM操作,并不会触发重绘和回流,把处理后的虚拟节点映射到真实DOM上,只触发一次重绘和回流。
二:diff算法
DIFF算法是DOM更新的一种算法,指页面被更新时,程序用哪种策略去做更新DOM
把树形结构按照层级分解,只比较同级元素。
给列表结构的每个单元添加唯一的key属性,方便比较。
React 只会匹配相同 class 的 component(这里面的class指的是组件的名字)
合并操作,调用 component 的 setState 方法的时候, React 将其标记为 - dirty.到每一个事件循环结束, React 检查所有标记 dirty的 component重新绘制.
选择性子树渲染。开发人员可以重写shouldComponentUpdate提高diff的性能
#
三:react性能优化方案
重写shouldComponentUpdate来避免不必要的dom操作
使用 production 版本的react.js
使用key来帮助React识别列表中所有子组件的最小变化