持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
diff介绍
组件并不是真实的DOM节点,而是存在于内存之中的一种数据结构,叫做虚拟DOM (virtual DOM)。只有当它插入
文档以后,才会变成真实的DOM。根据React的设计,所有的DOM变动,都先在虚拟DOM上发生,然后再将实际发生变动的
部分,反映在真实DOM上,这种算法叫做DOM diff
diff算法:
dif作为VirtualDOM的加速器, 其算法上的改进优化是React整个界面渲染的基础和性能的保障
dif会帮助我们就散出VirtualDOM中真正变化的部分,并只针对该部分进行原生DOM操作,而不是渲染整个页面。从而
保证了每次操作更新后页面的高效渲染
React将VirtualDOM树转换为actualDOM的最少操作过程称为调和(reconciliation)
dif算法就是调和过程的具体实现
tree diff
DOM节点跨层级的移动操作很少,忽略不计
React对树的算法进行了简洁明了的优化:只对树进行分层比较,两棵树只会对同一层次的节点进行比较。
React只会对相同层级的DOM节点进行比较,即同一个父节点下的所有子节点,当发现该节点已经不存在了,就会删除
该节点和其所有子节点,不会再做进一步的比较。
而如果真的出现了跨层级的移动,并不会出现移动操作,而是使移动的跟节点被删除而后重新创建
component diff
拥有相同类的两个组件将会生成相似的树形结构,拥有不种类的两个组件将会生成不同的树形结构
如果是同一类型的组件,按原策略继续比较VirtualDOM树即可
如果不是,则将该组件判断为dirty component,从而替换整个组件下的所有子节点
对于同一类型的组件,可能其virtualDOM没有任何变化,如果能确切的知道这一点,那么就可以节省大量的diff
运算时间,因此,React允许用户通过shouldComponentUpdate()来判断是否需要组件进行算法分析
element diff
对于同一层级的一组子节点,可以通过他们唯一的ID来区分
当节点处于同一层级的时候,diff提供了三种节点操作:
INSERT_MARKUP(插入)、OVE_EXISTING(移动)、REMOVE_NODE(删除)
插入:新的组件不在旧的集合中,也就是一个全新的节点
旧的集合中有新的组件类型,且element是可更新的类型,geterateComponent-Children已经调用receiveComponent,
这种情况下prevChild,就需要做移动操作,可以复用以前的DOM节点
旧组件类型在新的集合里也有,但对应的element不同则不能直接复用和更新,需要执行删除操作,或者旧组件不在
新集合里,也要执行删除操作