一、虚拟DOM:
(1)DOM操作慢是相比于JS原生API,如数组操作
(2)任何基于DOM操作的库(React、Vue)对DOM操作都不可能比DOM快
二、虚拟DOM的优点
(1)减少DOM的操作
减少DOM的操作的次数:虚拟DOM可以将多次操作合并为一次操作,比如添加1000个节点,却是一个一个操作的,虚拟DOM则是往数组中添加一千个文本,虚拟DOM可以合并为一次
减少DOM操作的范围:虚拟DOM借助DOM diff可以把多余的操作省掉,如果页面中990个节点,现在需要添加10个,虚拟DOM通过diff算法对比节点,只操作需要更新的10个节点就好了,而js是无法判断的,会对所有的DOM进行操作
三、虚拟DOM的diff算法(对比算法)
diff同层对比,
for循环用index做键值的缺点,就是不能知道它是不是唯一的值
(2)跨平台
实际上虚拟DOM就是一个JS对象
React使用React.createElement('div',{className:'red',onClick:()=>{}},[
createElement('span',{},'span1')
])
简写:需要引入JSX
<div onClick={()=>{}} className=""></div>
虚拟DOM是什么:
一个能代表DOM树的对象,通常含有标签名、标签上的属性、事件监听和子元素们,以及其他属性
优点:
能减少不必要的DOM操作、能跨平台渲染
缺点:
需要额外的创建函数,如createElement,但是可以用JSX来简化成XML写法,严重依赖打包工具,需要添加额外的构建过程
结论:
数据范围在合理范围之内的时候,使用虚拟DOM是可以做到优化的,效率更高,但是React在DOM超过十万的话就需要很长的时间,这个时候使用原生JS 操作DOM
不使用index作为for循环key值的文章
【注释】为什么在for循环中最好不要使用index来作为key值,主要是因为虚拟DOM的diff算法,当遍历一个数组的时候使用了index作为key值,如果这个数组中的数据进行打乱,因为diff算法是根据key值去进行新旧对比的,如果发现key所对应的数据不一致的情况下,就会进行重新渲染,删除原来的旧元素,重新生成新的元素。
而如果不是使用index作为key值,使用的是唯一data数据唯一标识的话,diff算法会根据key去对比发现原来的DOM元素只是调换了位置,就不会去删除旧元素而去生成新的元素了。
不使用index作为key值其实是方便了diff算法,使其更加高效,
三、性能优化(参考)
由于react中性能主要耗费在于update阶段的diff算法,因此性能优化也主要针对diff算法。
1、减少diff算法触发次数
减少diff算法触发次数实际上就是减少update流程的次数。
正常进入update流程有三种方式:
1.setState
setState机制在正常运行时,由于批更新策略,已经降低了update过程的触发次数。
因此,setState优化主要在于非批更新阶段中(timeout/Promise回调),减少setState的触发次数。
常见的业务场景即处理接口回调时,无论数据处理多么复杂,保证最后只调用一次setState。
2.父组件render
父组件的render必然会触发子组件进入update阶段(无论props是否更新)。此时最常用的优化方案即为shouldComponentUpdate方法。
最常见的方式为进行this.props和this.state的浅比较来判断组件是否需要更新。或者直接使用PureComponent,原理一致。
需要注意的是,父组件的render函数如果写的不规范,将会导致上述的策略失效。