面试题答案
一键面试React虚拟DOM比对算法与策略
- 策略:
- 分层比较:React将虚拟DOM树按层级进行比较,只对同一层级的节点进行对比,而非跨层级比较,这样可以大大减少比较的复杂度。例如,一个有父子关系的树形结构,先比较父节点层级,再比较子节点层级,不会在父节点层级还未比较完时就去比较子节点与父节点的跨层级情况。
- 节点类型比较优先:首先比较节点的类型,如
div
和span
是不同类型节点。如果节点类型不同,React会直接删除旧节点,创建新节点,而不会再深入比较其内部子节点。例如,旧节点是<div>
,新节点是<span>
,则直接抛弃旧的<div>
及其子树,创建新的<span>
及其子树。 - key属性的运用:当节点类型相同时,若子节点有
key
属性,React会根据key
来识别节点,从而更高效地进行比对。key
就像是节点的唯一标识,通过key
可以快速定位到具体的节点,而不是盲目地按照顺序比对。比如一个列表项,每个列表项都有一个唯一的key
,在列表项顺序变化或增减时,React可以根据key
快速确定哪些项需要移动、新增或删除。
- 算法:
- diff算法:React采用的核心算法是
diff
算法。它在同一层级的节点间进行比较,通过标记变化的方式来记录节点的差异。在比较过程中,React会生成一个patch
对象,这个对象记录了节点的插入、删除、移动、属性变化等操作。例如,当一个列表中新增了一个元素,diff
算法会在patch
对象中记录插入操作及新元素的相关信息。
- diff算法:React采用的核心算法是
发现差异后更新实际DOM
- 更新操作分类:
- 属性更新:当发现节点的属性有变化时,React会直接更新实际DOM的属性。例如,一个
<input>
标签原来的value
属性值为"oldValue"
,新的虚拟DOM中value
变为"newValue"
,React会找到对应的实际DOM<input>
元素,直接修改其value
属性为"newValue"
。 - 文本更新:如果节点是文本节点,且文本内容发生变化,React会直接更新实际DOM中的文本内容。比如一个
<p>
标签内的文本从"Hello"
变为"World"
,React会找到对应的<p>
元素,将其文本内容替换为"World"
。 - 节点插入与删除:当发现新的虚拟DOM中有新节点(旧的虚拟DOM中不存在),React会在实际DOM中插入该节点;若旧的虚拟DOM中的节点在新的虚拟DOM中不存在,则从实际DOM中删除该节点。例如,在一个列表中新增一项,React会在实际DOM的列表容器中插入新的列表项元素;若删除一项,会从实际DOM的列表容器中移除对应的列表项元素。
- 节点移动:若通过
key
识别出节点只是位置发生变化,React会在实际DOM中移动该节点。比如一个列表项从第二个位置移动到第四个位置,React会在实际DOM中找到该列表项元素,并将其从原来的第二个位置移动到第四个位置。
- 属性更新:当发现节点的属性有变化时,React会直接更新实际DOM的属性。例如,一个
- 批量更新: React并不会在每次发现差异时就立即更新实际DOM,而是采用批量更新策略。它会将所有的DOM更新操作先收集起来,等到所有的状态变化处理完后,一次性将这些更新应用到实际DOM上。这样可以减少实际DOM的重绘和回流次数,提高性能。例如,在一个函数中多次修改状态,这些状态变化对应的DOM更新操作会被批量收集,最后统一更新实际DOM。