理解Virtual DOM

理解Virtual DOM
最新回答
无理诗人

2026-01-30 14:11:10

Virtual DOM(虚拟DOM)是一种通过JavaScript模拟真实DOM的技术,旨在通过减少直接操作真实DOM的次数来提升性能。

核心原则
  • DOM操作是最昂贵的:直接操作真实DOM会导致频繁的重绘和回流,影响性能。
  • 精准更新节点:通过算法找出本次必须更新的节点,其他节点不更新,从而减少不必要的DOM操作。
什么是Virtual DOM
  • 用JavaScript模拟真实DOM:

  • 作用:

    DOM对比放在JS层完成:通过JavaScript计算差异,减少直接操作真实DOM的次数。

    提高重绘性能:通过批量更新和最小化DOM操作,提升页面渲染效率。

Virtual DOM的实现
  • 以snabbdom为例:

    h函数:生成虚拟节点(Vnode)。

    patch函数:对比新旧虚拟节点,并更新真实DOM。

Diff算法
  • 核心目标:找出必须更新的DOM节点。
  • 核心API:

    patch(container, Vnode):将虚拟DOM转化为真实DOM,并挂载到容器上。

    patch(Vnode, newVnode):比较两个虚拟节点,递归更新子节点。

  • 实现思路:

    递归比较子节点:如果子节点不同,则进行更新。

    更新操作:包括节点的新增、删除、重新排序,以及属性、样式和事件绑定的更新。

React Diff策略
  • 传统Diff算法的复杂度为O(n3),性能无法接受。React通过以下策略将复杂度优化至O(n):

    策略一:忽略跨层级移动:

    Web UI中DOM节点跨层级移动操作极少,可忽略不计。

    React通过updateDepth对Virtual DOM树进行层级控制,只比较同一父节点下的子节点。

    策略二:相同类生成相似树形结构:

    相同类的组件生成相似树形结构,不同类的组件生成不同树形结构。

    如果是同一类型组件,继续比较Virtual DOM树;如果不是,则替换整个组件及其子节点。

    允许通过shouldComponentUpdate()判断组件是否需要Diff。

    策略三:同一层级子节点通过唯一ID区分:

    对同一层级的子节点,通过唯一ID(如key)进行区分。

    三种节点操作:

    INSERT_MARKUP(插入):新组件类型不在老集合中,需插入新节点。

    MOVE_EXISTING(移动):老集合中有新组件类型,且可更新,需移动节点。

    REMOVE_NODE(删除):老组件类型在新集合中不同,或不在新集合中,需删除节点。

总结
  • 复杂度优化:React通过大胆的Diff策略,将O(n3)复杂度问题转换为O(n)复杂度问题。
  • Tree Diff优化:通过分层求异策略,减少比较范围。
  • Component Diff优化:通过相同类生成相似树形结构、不同类生成不同树形结构的策略,减少不必要的比较。
  • Element Diff优化:通过设置唯一key的策略,精准定位节点操作。
  • 开发建议:

    保持稳定的DOM结构有助于提升性能。

    减少将最后一个节点移动到列表首部的操作,避免影响渲染性能。