直接操做DOM必定比虚拟DOM操做耗时吗?算法
或者一次直接DOM操做必定比一次虚拟DOM操做耗时吗?segmentfault
1)虚拟DOM的本质就是一个JS对象,虚拟DOM减小了真实DOM的操做,当修改数据的时候,就是修改虚拟DOM产生全新的虚拟DOM,数组
新旧虚拟DOM使用diff算法,获得patch(也就是须要修改的部分),而后将这个patch打到浏览器的DOM上浏览器
(减小重绘和回流,从而达到性能优化的目的)缓存
2)每次DOM操做会引发重绘或者回流,频繁的真实DOM的修改会触发屡次的排版和重绘至关耗性能(彻底增删改)性能优化
一)、虚拟DOMdom
1)DOM的本质是什么?异步
DOM是浏览器中的概念,用js对象表示页面上的元素,并提供操做DOM对象的API性能
2)React中的虚拟DOM是什么?优化
虚拟DOM就是一个JS对象(数据+JXS模板),用一个js对象来描述真实的DOM
虚拟DOM为何会提升性能?
虚拟DOM提升性能,不是说不操做DOM,而是减小操做DOM的次数,减小回流和重绘
虚拟 dom 至关于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操做,从而提升性能
1)用 JavaScript 对象结构表示 DOM 树的结构;
2)而后用这个树构建一个真正的 DOM 树,插到文档当中
3)当状态变动的时候,从新构造一棵新的对象树
4)而后用新的树和旧的树进行比较,记录两棵树差别
5)把 2所记录的差别应用到步骤 2)所构建的真正的 DOM 树上,视图就更新了
使用diff算法比较新旧虚拟DOM----即比较两个js对象不怎么耗性能,而比较两个真实的DOM比较耗性能,从而虚拟DOM极大的提高了性能
虚拟DOM发生比对的时机:当数据发生变化的时候会发生虚拟DOM的比对(props和state发生变化,而props的变化是父组件的state发生变化,归根结底就是调用setState()的时候state发生变化,而后虚拟DOM发生比对)。
setState()方法是异步的,从而提高性能-----例如调用3次setState()变动数据,而调用时间间隔小,React能够将3次setState合并成一次setState,只作一次虚拟DOM比对,而后对DOM更新,从而省去两次额外虚拟DOM比对的性能损耗
调用setState()以后发生了什么?
1)首先,React 将setState()方法中传入的参数对象与组件当前的状态合并
2)而后,触发调和过程(Reconciliation)
3)通过调和过程后,React 会以相对高效的方式,根据新的状态构建 React 元素树
4)在 React 获得元素树以后,React 会自动计算出新的树与老树的节点差别,而后根据差别对界面进行最小化重渲染。
在差别计算算法中,React 可以相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是所有从新渲染。
3)虚拟DOM的目的?
实现页面中DOM元素的高效更新
二)、diff算法:同层比对,列表使用不一样的key值
React的DOM是同层比对的
diff算法指的就是两个虚拟DOM做比对,在diff算法中有个概念就是同级比对,首先比对顶层虚拟DOM节点是否一致,若是同样就接着比对下一层,若是不同,就中止向下比对,将原始页面中这个DOM及 下面的DOM所有删除掉,从新生成新的虚拟DOM,而后替换掉原始页面的DOM
存在问题:若是第一层虚拟DOM节点不一样,下面的都同,使用虚拟DOM的diff算法,则这些节点都不能使用了,会形成从新渲染的浪费。
优势:同层虚拟DOM比对,只须要一层层的比较,算法简单,比对的速度快
虽然会形成从新渲染的浪费,可是会大大减小两个虚拟DOM比对的性能消耗
列表中的元素使用不一样的key
虚拟DOM中的列表中同级元素的key值要不一样,使用diff算法,判断哪些元素是增删改,从而提升性能
列表中key的做用:
1)key是React用于跟踪哪些元素是增长、删除、修改的辅助标记,须要保证在同级元素中key的惟一性
2) React Diff 算法借助元素的 Key 值判断元素是新增、删除、修改,从而减小没必要要的元素重渲染。
3)React 还须要借助 Key 值来判断元素与本地状态的关联关系
问题:在循环中key值最好不要用index的缘由?
若是key值使用index的话,就可能没法使原始的虚拟DOM中的key值和新的虚拟DOM中的key值一致,从而不能充分发挥diff算法的优点。
好比一个数组里有数据a b c,用index表示的key分别为0 1 2
当删除a时,b c的key分别为0 2,从而致使元素的新旧key值不同,即key值不稳定,因此key值就失去其存在的意义了
比较合适的key值有:id或者不同的内容
1)tree diff
新旧两颗DOM树,逐层对比的过程,就是Tree Diff;当整颗DOM树逐层对比完毕,则全部按需更新的元素都能找到
2)component diff
在进行Tree Diff的时候,每一层中,组件级别的对比,叫作Component Diff
若是对比先后,组件类型相同,则暂时认为此组件不须要更新;
若是对比先后,组件类型不一样,则须要移除旧组件。建立新组建,并追加到页面上
3)element diff
在进行组件对比的时候,若是两个组件类型相同,则须要进行元素级别的对比,这叫作element diff