欢迎光临
我们一直在努力

说说真实DOM和虚拟DOM的区别?它们的优缺点是什么?:深入理解前端渲染机制与性能优化之道

一、真实DOM与虚拟DOM的本质概念

1.1 真实DOM的定义与结构

真实DOM是浏览器原生提供的文档对象模型,它是HTML或XML文档在内存中的对象表示。当浏览器解析HTML时,会构建出一棵由节点组成的树形结构,每个节点都是DOM对象,包含标签名、属性、子节点、文本内容等信息。

真实DOM的核心特点如下:

  • 它是浏览器原生API,由C++实现,运行在浏览器底层
  • 每个DOM节点都是一个重量级对象,包含大量属性和方法
  • DOM操作会触发浏览器的重排与重绘,性能开销较大
  • 它是页面可视元素的直接映射,操作DOM会立即影响页面呈现
  • 一个真实DOM节点的简化创建过程如下:

    const div = document.createElement('div');
    div.id = 'app';
    div.className = 'container';
    div.textContent = 'Hello World';

    上述代码创建的div对象在浏览器中包含上百个属性和方法,如childNodes、parentNode、style、addEventListener等,这些都是浏览器为每个DOM节点提供的标准接口。

    1.2 虚拟DOM的定义与结构

    虚拟DOM是用普通JavaScript对象来描述真实DOM的一种轻量级数据结构。它本质上是一棵普通的JavaScript对象树,通过属性来描述DOM节点的标签、类型、属性和子节点,而不是真正的浏览器DOM节点。

    虚拟DOM的核心特点如下:

  • 它是普通的JavaScript对象,创建和操作成本极低
  • 不依赖浏览器环境,可以运行在Node.js等服务端
  • 通过Diff算法比对前后两棵虚拟DOM树的差异
  • 最终将差异批量应用到真实DOM,减少直接操作DOM的次数
  • 一个虚拟DOM节点的简化结构如下:

    {
    tag: 'div',
    props: {
    id: 'app',
    className: 'container'
    },
    children: [
    {
    tag: 'span',
    props: {},
    children: ['Hello World']
    }
    ]
    }

    在React中,虚拟DOM通过createElement函数创建:

    const element = React.createElement(
    'div',
    { id: 'app', className: 'container' },
    React.createElement('span', null, 'Hello World')
    );

    1.3 两者的核心关系

    虚拟DOM与真实DOM并非对立关系,而是协作关系。虚拟DOM是真实DOM在JavaScript层的抽象映射,最终仍需转换为真实DOM才能在页面上呈现。它们的关系可以用如下流程描述:

    #publish-mermaid-1785720872674-0{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1785720872674-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720872674-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720872674-0 .error-icon{fill:#552222;}#publish-mermaid-1785720872674-0 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1785720872674-0 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1785720872674-0 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1785720872674-0 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1785720872674-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1785720872674-0 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1785720872674-0 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1785720872674-0 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1785720872674-0 .marker.cross{stroke:#333333;}#publish-mermaid-1785720872674-0 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1785720872674-0 p{margin:0;}#publish-mermaid-1785720872674-0 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1785720872674-0 .cluster-label text{fill:#333;}#publish-mermaid-1785720872674-0 .cluster-label span{color:#333;}#publish-mermaid-1785720872674-0 .cluster-label span p{background-color:transparent;}#publish-mermaid-1785720872674-0 .label text,#publish-mermaid-1785720872674-0 span{fill:#333;color:#333;}#publish-mermaid-1785720872674-0 .node rect,#publish-mermaid-1785720872674-0 .node circle,#publish-mermaid-1785720872674-0 .node ellipse,#publish-mermaid-1785720872674-0 .node polygon,#publish-mermaid-1785720872674-0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720872674-0 .rough-node .label text,#publish-mermaid-1785720872674-0 .node .label text,#publish-mermaid-1785720872674-0 .image-shape .label,#publish-mermaid-1785720872674-0 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1785720872674-0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1785720872674-0 .rough-node .label,#publish-mermaid-1785720872674-0 .node .label,#publish-mermaid-1785720872674-0 .image-shape .label,#publish-mermaid-1785720872674-0 .icon-shape .label{text-align:center;}#publish-mermaid-1785720872674-0 .node.clickable{cursor:pointer;}#publish-mermaid-1785720872674-0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1785720872674-0 .arrowheadPath{fill:#333333;}#publish-mermaid-1785720872674-0 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1785720872674-0 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1785720872674-0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720872674-0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1785720872674-0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720872674-0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1785720872674-0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1785720872674-0 .cluster text{fill:#333;}#publish-mermaid-1785720872674-0 .cluster span{color:#333;}#publish-mermaid-1785720872674-0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1785720872674-0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1785720872674-0 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1785720872674-0 .icon-shape,#publish-mermaid-1785720872674-0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720872674-0 .icon-shape p,#publish-mermaid-1785720872674-0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1785720872674-0 .icon-shape .label rect,#publish-mermaid-1785720872674-0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720872674-0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1785720872674-0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1785720872674-0 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1785720872674-0 [data-look=\”neo\”].node rect,#publish-mermaid-1785720872674-0 [data-look=\”neo\”].cluster rect,#publish-mermaid-1785720872674-0 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872674-0 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1785720872674-0 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720872674-0 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872674-0 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1785720872674-0 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872674-0 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1785720872674-0 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872674-0 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872674-0 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    数据状态变更

    生成新的虚拟DOM树

    与旧虚拟DOM树进行Diff比对

    计算出最小变更集合

    批量更新真实DOM

    页面重新渲染

    从流程图可以看出,虚拟DOM充当了数据与真实DOM之间的中间层,通过最小化真实DOM操作来提升性能。

    二、真实DOM与虚拟DOM的区别详解

    2.1 渲染流程对比

    真实DOM的渲染流程相对直接:开发者通过原生API操作DOM,浏览器立即响应并触发重排或重绘。每次操作都会引发浏览器的渲染流程,缺乏批量处理的机制。

    真实DOM渲染流程如下:

    #publish-mermaid-1785720872861-1{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1785720872861-1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720872861-1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720872861-1 .error-icon{fill:#552222;}#publish-mermaid-1785720872861-1 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1785720872861-1 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1785720872861-1 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1785720872861-1 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1785720872861-1 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1785720872861-1 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1785720872861-1 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1785720872861-1 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1785720872861-1 .marker.cross{stroke:#333333;}#publish-mermaid-1785720872861-1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1785720872861-1 p{margin:0;}#publish-mermaid-1785720872861-1 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1785720872861-1 .cluster-label text{fill:#333;}#publish-mermaid-1785720872861-1 .cluster-label span{color:#333;}#publish-mermaid-1785720872861-1 .cluster-label span p{background-color:transparent;}#publish-mermaid-1785720872861-1 .label text,#publish-mermaid-1785720872861-1 span{fill:#333;color:#333;}#publish-mermaid-1785720872861-1 .node rect,#publish-mermaid-1785720872861-1 .node circle,#publish-mermaid-1785720872861-1 .node ellipse,#publish-mermaid-1785720872861-1 .node polygon,#publish-mermaid-1785720872861-1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720872861-1 .rough-node .label text,#publish-mermaid-1785720872861-1 .node .label text,#publish-mermaid-1785720872861-1 .image-shape .label,#publish-mermaid-1785720872861-1 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1785720872861-1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1785720872861-1 .rough-node .label,#publish-mermaid-1785720872861-1 .node .label,#publish-mermaid-1785720872861-1 .image-shape .label,#publish-mermaid-1785720872861-1 .icon-shape .label{text-align:center;}#publish-mermaid-1785720872861-1 .node.clickable{cursor:pointer;}#publish-mermaid-1785720872861-1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1785720872861-1 .arrowheadPath{fill:#333333;}#publish-mermaid-1785720872861-1 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1785720872861-1 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1785720872861-1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720872861-1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1785720872861-1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720872861-1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1785720872861-1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1785720872861-1 .cluster text{fill:#333;}#publish-mermaid-1785720872861-1 .cluster span{color:#333;}#publish-mermaid-1785720872861-1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1785720872861-1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1785720872861-1 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1785720872861-1 .icon-shape,#publish-mermaid-1785720872861-1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720872861-1 .icon-shape p,#publish-mermaid-1785720872861-1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1785720872861-1 .icon-shape .label rect,#publish-mermaid-1785720872861-1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720872861-1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1785720872861-1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1785720872861-1 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1785720872861-1 [data-look=\”neo\”].node rect,#publish-mermaid-1785720872861-1 [data-look=\”neo\”].cluster rect,#publish-mermaid-1785720872861-1 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872861-1 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1785720872861-1 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720872861-1 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872861-1 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1785720872861-1 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872861-1 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1785720872861-1 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872861-1 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872861-1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    JavaScript操作DOM API

    浏览器立即解析

    触发重排Reflow

    触发重绘Repaint

    页面更新

    等待下一次操作

    虚拟DOM的渲染流程则引入了中间层:数据变化先反映在虚拟DOM上,通过Diff算法计算出差异,再将差异批量应用到真实DOM。这种方式将多次DOM操作合并为一次,显著减少了浏览器的重排重绘次数。

    虚拟DOM渲染流程如下:

    #publish-mermaid-1785720872942-2{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1785720872942-2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720872942-2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720872942-2 .error-icon{fill:#552222;}#publish-mermaid-1785720872942-2 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1785720872942-2 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1785720872942-2 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1785720872942-2 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1785720872942-2 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1785720872942-2 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1785720872942-2 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1785720872942-2 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1785720872942-2 .marker.cross{stroke:#333333;}#publish-mermaid-1785720872942-2 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1785720872942-2 p{margin:0;}#publish-mermaid-1785720872942-2 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1785720872942-2 .cluster-label text{fill:#333;}#publish-mermaid-1785720872942-2 .cluster-label span{color:#333;}#publish-mermaid-1785720872942-2 .cluster-label span p{background-color:transparent;}#publish-mermaid-1785720872942-2 .label text,#publish-mermaid-1785720872942-2 span{fill:#333;color:#333;}#publish-mermaid-1785720872942-2 .node rect,#publish-mermaid-1785720872942-2 .node circle,#publish-mermaid-1785720872942-2 .node ellipse,#publish-mermaid-1785720872942-2 .node polygon,#publish-mermaid-1785720872942-2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720872942-2 .rough-node .label text,#publish-mermaid-1785720872942-2 .node .label text,#publish-mermaid-1785720872942-2 .image-shape .label,#publish-mermaid-1785720872942-2 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1785720872942-2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1785720872942-2 .rough-node .label,#publish-mermaid-1785720872942-2 .node .label,#publish-mermaid-1785720872942-2 .image-shape .label,#publish-mermaid-1785720872942-2 .icon-shape .label{text-align:center;}#publish-mermaid-1785720872942-2 .node.clickable{cursor:pointer;}#publish-mermaid-1785720872942-2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1785720872942-2 .arrowheadPath{fill:#333333;}#publish-mermaid-1785720872942-2 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1785720872942-2 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1785720872942-2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720872942-2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1785720872942-2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720872942-2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1785720872942-2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1785720872942-2 .cluster text{fill:#333;}#publish-mermaid-1785720872942-2 .cluster span{color:#333;}#publish-mermaid-1785720872942-2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1785720872942-2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1785720872942-2 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1785720872942-2 .icon-shape,#publish-mermaid-1785720872942-2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720872942-2 .icon-shape p,#publish-mermaid-1785720872942-2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1785720872942-2 .icon-shape .label rect,#publish-mermaid-1785720872942-2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720872942-2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1785720872942-2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1785720872942-2 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1785720872942-2 [data-look=\”neo\”].node rect,#publish-mermaid-1785720872942-2 [data-look=\”neo\”].cluster rect,#publish-mermaid-1785720872942-2 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872942-2 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1785720872942-2 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720872942-2 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872942-2 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1785720872942-2 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872942-2 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1785720872942-2 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872942-2 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720872942-2 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    数据状态变更

    生成新虚拟DOM树

    Diff算法比对

    计算最小变更集

    批量更新真实DOM

    一次性重排重绘

    页面更新

    两者的关键区别在于:真实DOM是同步的、即时的操作,而虚拟DOM是异步的、批量的操作。

    2.2 性能开销对比

    真实DOM的性能开销主要体现在两个方面:

  • DOM对象本身较为沉重,创建和销毁开销大
  • 每次DOM操作都可能触发重排重绘,频繁操作性能急剧下降
  • 虚拟DOM的性能优势体现在:

  • JavaScript对象创建成本极低,远低于DOM节点
  • Diff算法在JavaScript层完成,避免频繁触碰DOM
  • 批量更新机制减少重排重绘次数
  • 但虚拟DOM并非在所有场景下都更快。对于单次简单DOM操作,直接操作真实DOM反而比经过虚拟DOM的中转更高效。虚拟DOM的优势体现在频繁、复杂的UI更新场景。

    性能对比示意如下:

    | 操作类型 | 真实DOM | 虚拟DOM |

    |———|———|———|

    | 单次简单操作 | 快 | 略慢(多一层中转) |

    | 大量频繁更新 | 慢(频繁重排) | 快(批量更新) |

    | 首次渲染 | 快 | 略慢(需构建虚拟树) |

    | 复杂列表更新 | 慢 | 快(配合Key优化) |

    2.3 跨平台能力对比

    真实DOM强依赖浏览器环境,无法在Node.js或其他非浏览器环境中运行。这导致服务端渲染(SSR)等场景下,直接操作DOM会报错。

    虚拟DOM因为是纯JavaScript对象,具有天然的跨平台能力:

  • 浏览器端:转换为真实DOM
  • 服务端:转换为HTML字符串
  • 移动端:转换为原生组件(如React Native)
  • 桌面端:转换为原生控件
  • 跨平台工作原理如下:

    #publish-mermaid-1785720873011-3{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1785720873011-3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873011-3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873011-3 .error-icon{fill:#552222;}#publish-mermaid-1785720873011-3 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1785720873011-3 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1785720873011-3 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1785720873011-3 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1785720873011-3 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1785720873011-3 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1785720873011-3 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1785720873011-3 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1785720873011-3 .marker.cross{stroke:#333333;}#publish-mermaid-1785720873011-3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1785720873011-3 p{margin:0;}#publish-mermaid-1785720873011-3 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1785720873011-3 .cluster-label text{fill:#333;}#publish-mermaid-1785720873011-3 .cluster-label span{color:#333;}#publish-mermaid-1785720873011-3 .cluster-label span p{background-color:transparent;}#publish-mermaid-1785720873011-3 .label text,#publish-mermaid-1785720873011-3 span{fill:#333;color:#333;}#publish-mermaid-1785720873011-3 .node rect,#publish-mermaid-1785720873011-3 .node circle,#publish-mermaid-1785720873011-3 .node ellipse,#publish-mermaid-1785720873011-3 .node polygon,#publish-mermaid-1785720873011-3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873011-3 .rough-node .label text,#publish-mermaid-1785720873011-3 .node .label text,#publish-mermaid-1785720873011-3 .image-shape .label,#publish-mermaid-1785720873011-3 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1785720873011-3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1785720873011-3 .rough-node .label,#publish-mermaid-1785720873011-3 .node .label,#publish-mermaid-1785720873011-3 .image-shape .label,#publish-mermaid-1785720873011-3 .icon-shape .label{text-align:center;}#publish-mermaid-1785720873011-3 .node.clickable{cursor:pointer;}#publish-mermaid-1785720873011-3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1785720873011-3 .arrowheadPath{fill:#333333;}#publish-mermaid-1785720873011-3 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1785720873011-3 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1785720873011-3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873011-3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873011-3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873011-3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1785720873011-3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1785720873011-3 .cluster text{fill:#333;}#publish-mermaid-1785720873011-3 .cluster span{color:#333;}#publish-mermaid-1785720873011-3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1785720873011-3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1785720873011-3 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1785720873011-3 .icon-shape,#publish-mermaid-1785720873011-3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873011-3 .icon-shape p,#publish-mermaid-1785720873011-3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1785720873011-3 .icon-shape .label rect,#publish-mermaid-1785720873011-3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873011-3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1785720873011-3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1785720873011-3 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1785720873011-3 [data-look=\”neo\”].node rect,#publish-mermaid-1785720873011-3 [data-look=\”neo\”].cluster rect,#publish-mermaid-1785720873011-3 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873011-3 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1785720873011-3 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873011-3 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873011-3 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1785720873011-3 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873011-3 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1785720873011-3 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873011-3 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873011-3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}浏览器服务端移动端桌面端

    虚拟DOM树

    目标平台

    ReactDOM渲染为真实DOM

    ReactDOMServer渲染为HTML字符串

    ReactNative渲染为原生组件

    ReactNativeWindows渲染为原生控件

    这种跨平台能力是虚拟DOM最重要的优势之一,也是React等框架能够支撑多端开发的基础。

    三、真实DOM的优缺点分析

    3.1 真实DOM的优点

    真实DOM作为浏览器原生标准,具有以下优点:

  • 直接高效:对于单次操作,直接调用DOM API无需中间层,响应即时
  • 标准统一:W3C标准,所有浏览器一致支持,无需兼容处理
  • 学习成本低:API设计直观,如getElementById、appendChild等
  • 功能完整:提供完整的DOM操作能力,包括事件、样式、动画等
  • 调试方便:浏览器开发者工具直接可见,便于调试
  • 3.2 真实DOM的缺点

    真实DOM的主要缺点集中在性能和开发体验上:

  • 性能瓶颈:频繁操作触发大量重排重绘,页面卡顿
  • 同步阻塞:DOM操作是同步的,大量操作会阻塞主线程
  • 状态管理困难:手动维护DOM状态,代码容易混乱
  • 跨平台受限:强依赖浏览器,无法用于SSR或原生开发
  • 节点沉重:每个DOM节点包含大量属性,内存占用高
  • 一个典型的性能问题示例如下:

    // 真实DOM: 1000次操作触发1000次重排
    for (let i = 0; i < 1000; i++) {
    const li = document.createElement('li');
    li.textContent = `Item ${i}`;
    document.getElementById('list').appendChild(li);
    }

    上述代码每次appendChild都会触发一次重排,1000次循环将导致严重的性能问题。

    3.3 真实DOM的适用场景

    真实DOM适合以下场景:

  • 简单页面:页面交互少,DOM操作不频繁
  • 性能敏感的简单操作:如拖拽、动画等需要直接控制DOM的场景
  • 传统jQuery项目:不依赖现代框架的项目
  • 原生Web组件:使用Web Components标准开发
  • 学习教学:理解DOM基础原理
  • 四、虚拟DOM的优缺点分析

    4.1 虚拟DOM的优点

    虚拟DOM作为现代前端框架的核心技术,优势显著:

  • 性能优化:通过Diff算法和批量更新,最小化DOM操作
  • 跨平台:纯JavaScript对象,支持浏览器、服务端、移动端等多平台
  • 声明式开发:开发者只需描述数据状态,框架自动处理DOM更新
  • 组件化:天然支持组件化开发,代码复用性强
  • 状态驱动:UI是状态的映射,逻辑清晰可预测
  • 批量更新示例如下:

    // 虚拟DOM: 1000次状态变更只触发一次重排
    function App() {
    const [items, setItems] = useState([]);
    useEffect(() => {
    const newItems = [];
    for (let i = 0; i < 1000; i++) {
    newItems.push(`Item ${i}`);
    }
    setItems(newItems); // 一次性更新
    }, []);
    return (
    <ul>
    {items.map((item, index) => (
    <li key={index}>{item}</li>
    ))}
    </ul>
    );
    }

    上述代码中,1000个列表项的更新通过虚拟DOM的批量机制,最终只触发一次DOM操作。

    4.2 虚拟DOM的缺点

    虚拟DOM并非完美,也存在以下不足:

  • 首次渲染较慢:需要先构建虚拟DOM树再转换为真实DOM,多了一层开销
  • 内存占用:维护虚拟DOM树需要额外内存
  • Diff算法开销:对比两棵树需要计算成本
  • 不适合极简操作:对于简单的单次操作,虚拟DOM反而比直接操作DOM慢
  • 调试复杂性:虚拟DOM是中间层,调试时需要理解其映射关系
  • 虚拟DOM的性能边界如下:

    #publish-mermaid-1785720873084-4{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1785720873084-4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873084-4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873084-4 .error-icon{fill:#552222;}#publish-mermaid-1785720873084-4 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1785720873084-4 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1785720873084-4 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1785720873084-4 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1785720873084-4 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1785720873084-4 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1785720873084-4 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1785720873084-4 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1785720873084-4 .marker.cross{stroke:#333333;}#publish-mermaid-1785720873084-4 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1785720873084-4 p{margin:0;}#publish-mermaid-1785720873084-4 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1785720873084-4 .cluster-label text{fill:#333;}#publish-mermaid-1785720873084-4 .cluster-label span{color:#333;}#publish-mermaid-1785720873084-4 .cluster-label span p{background-color:transparent;}#publish-mermaid-1785720873084-4 .label text,#publish-mermaid-1785720873084-4 span{fill:#333;color:#333;}#publish-mermaid-1785720873084-4 .node rect,#publish-mermaid-1785720873084-4 .node circle,#publish-mermaid-1785720873084-4 .node ellipse,#publish-mermaid-1785720873084-4 .node polygon,#publish-mermaid-1785720873084-4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873084-4 .rough-node .label text,#publish-mermaid-1785720873084-4 .node .label text,#publish-mermaid-1785720873084-4 .image-shape .label,#publish-mermaid-1785720873084-4 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1785720873084-4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1785720873084-4 .rough-node .label,#publish-mermaid-1785720873084-4 .node .label,#publish-mermaid-1785720873084-4 .image-shape .label,#publish-mermaid-1785720873084-4 .icon-shape .label{text-align:center;}#publish-mermaid-1785720873084-4 .node.clickable{cursor:pointer;}#publish-mermaid-1785720873084-4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1785720873084-4 .arrowheadPath{fill:#333333;}#publish-mermaid-1785720873084-4 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1785720873084-4 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1785720873084-4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873084-4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873084-4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873084-4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1785720873084-4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1785720873084-4 .cluster text{fill:#333;}#publish-mermaid-1785720873084-4 .cluster span{color:#333;}#publish-mermaid-1785720873084-4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1785720873084-4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1785720873084-4 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1785720873084-4 .icon-shape,#publish-mermaid-1785720873084-4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873084-4 .icon-shape p,#publish-mermaid-1785720873084-4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1785720873084-4 .icon-shape .label rect,#publish-mermaid-1785720873084-4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873084-4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1785720873084-4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1785720873084-4 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1785720873084-4 [data-look=\”neo\”].node rect,#publish-mermaid-1785720873084-4 [data-look=\”neo\”].cluster rect,#publish-mermaid-1785720873084-4 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873084-4 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1785720873084-4 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873084-4 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873084-4 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1785720873084-4 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873084-4 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1785720873084-4 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873084-4 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873084-4 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}简单操作复杂频繁更新

    操作复杂度

    是否值得使用虚拟DOM

    直接操作真实DOM更快

    虚拟DOM批量更新更优

    虚拟DOM反而增加开销

    虚拟DOM优势明显

    4.3 虚拟DOM的适用场景

    虚拟DOM适合以下场景:

  • 复杂交互应用:频繁的UI更新和状态变化
  • 单页应用(SPA):大量组件动态渲染
  • 跨平台应用:需要同时支持Web、移动端、服务端渲染
  • 数据驱动应用:数据频繁变化,UI需自动同步
  • 大型团队协作:声明式开发模式便于维护和协作
  • 五、虚拟DOM的Diff算法与更新机制

    5.1 Diff算法核心思想

    Diff算法是虚拟DOM性能优化的核心,其目标是高效地比较新旧两棵虚拟DOM树,找出最小变更集合。由于完整的树Diff时间复杂度为O(n^3),在实际应用中不可接受,因此React等框架采用了启发式策略,将复杂度降为O(n)。

    Diff算法的三大假设如下:

  • 同层比较:只比较同一层级的节点,不跨层比较
  • 类型不同直接替换:节点类型不同,直接销毁旧节点创建新节点
  • Key标识:通过Key识别同一节点的位置变化
  • Diff流程如下:

    #publish-mermaid-1785720873139-5{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1785720873139-5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873139-5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873139-5 .error-icon{fill:#552222;}#publish-mermaid-1785720873139-5 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1785720873139-5 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1785720873139-5 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1785720873139-5 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1785720873139-5 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1785720873139-5 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1785720873139-5 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1785720873139-5 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1785720873139-5 .marker.cross{stroke:#333333;}#publish-mermaid-1785720873139-5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1785720873139-5 p{margin:0;}#publish-mermaid-1785720873139-5 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1785720873139-5 .cluster-label text{fill:#333;}#publish-mermaid-1785720873139-5 .cluster-label span{color:#333;}#publish-mermaid-1785720873139-5 .cluster-label span p{background-color:transparent;}#publish-mermaid-1785720873139-5 .label text,#publish-mermaid-1785720873139-5 span{fill:#333;color:#333;}#publish-mermaid-1785720873139-5 .node rect,#publish-mermaid-1785720873139-5 .node circle,#publish-mermaid-1785720873139-5 .node ellipse,#publish-mermaid-1785720873139-5 .node polygon,#publish-mermaid-1785720873139-5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873139-5 .rough-node .label text,#publish-mermaid-1785720873139-5 .node .label text,#publish-mermaid-1785720873139-5 .image-shape .label,#publish-mermaid-1785720873139-5 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1785720873139-5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1785720873139-5 .rough-node .label,#publish-mermaid-1785720873139-5 .node .label,#publish-mermaid-1785720873139-5 .image-shape .label,#publish-mermaid-1785720873139-5 .icon-shape .label{text-align:center;}#publish-mermaid-1785720873139-5 .node.clickable{cursor:pointer;}#publish-mermaid-1785720873139-5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1785720873139-5 .arrowheadPath{fill:#333333;}#publish-mermaid-1785720873139-5 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1785720873139-5 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1785720873139-5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873139-5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873139-5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873139-5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1785720873139-5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1785720873139-5 .cluster text{fill:#333;}#publish-mermaid-1785720873139-5 .cluster span{color:#333;}#publish-mermaid-1785720873139-5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1785720873139-5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1785720873139-5 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1785720873139-5 .icon-shape,#publish-mermaid-1785720873139-5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873139-5 .icon-shape p,#publish-mermaid-1785720873139-5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1785720873139-5 .icon-shape .label rect,#publish-mermaid-1785720873139-5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873139-5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1785720873139-5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1785720873139-5 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1785720873139-5 [data-look=\”neo\”].node rect,#publish-mermaid-1785720873139-5 [data-look=\”neo\”].cluster rect,#publish-mermaid-1785720873139-5 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873139-5 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1785720873139-5 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873139-5 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873139-5 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1785720873139-5 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873139-5 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1785720873139-5 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873139-5 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873139-5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}相同不同有Key无Key

    新旧虚拟DOM树

    同层节点比较

    节点类型是否相同

    更新属性

    替换整个节点

    递归比较子节点

    销毁旧节点及子树

    是否有Key

    按Key匹配复用

    按索引顺序比较

    输出变更集合

    批量更新真实DOM

    5.2 同层比较策略

    同层比较是Diff算法最重要的优化策略。它假设DOM的跨层级移动很少发生,因此只比较同一层级的节点。如果发现某节点在新树中消失了,不会去其他层级查找,而是直接销毁。

    同层比较示例:

    // 旧树
    {
    tag: 'div',
    children: [
    { tag: 'p', children: ['Hello'] }
    ]
    }
    // 新树
    {
    tag: 'div',
    children: [
    { tag: 'span', children: ['Hello'] }
    ]
    }

    在上述示例中,Diff算法发现p变成了span,类型不同,直接销毁p节点及其子树,创建新的span节点。即使两者的文本内容相同,也不会复用。

    5.3 Key的作用与原理

    Key是虚拟DOM Diff算法中识别节点的关键标识。在列表渲染时,Key帮助算法准确判断哪些节点是新增、删除或移动的,从而最大化节点复用,减少不必要的创建和销毁。

    Key的工作原理如下:

    #publish-mermaid-1785720873243-6{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1785720873243-6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873243-6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873243-6 .error-icon{fill:#552222;}#publish-mermaid-1785720873243-6 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1785720873243-6 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1785720873243-6 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1785720873243-6 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1785720873243-6 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1785720873243-6 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1785720873243-6 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1785720873243-6 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1785720873243-6 .marker.cross{stroke:#333333;}#publish-mermaid-1785720873243-6 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1785720873243-6 p{margin:0;}#publish-mermaid-1785720873243-6 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1785720873243-6 .cluster-label text{fill:#333;}#publish-mermaid-1785720873243-6 .cluster-label span{color:#333;}#publish-mermaid-1785720873243-6 .cluster-label span p{background-color:transparent;}#publish-mermaid-1785720873243-6 .label text,#publish-mermaid-1785720873243-6 span{fill:#333;color:#333;}#publish-mermaid-1785720873243-6 .node rect,#publish-mermaid-1785720873243-6 .node circle,#publish-mermaid-1785720873243-6 .node ellipse,#publish-mermaid-1785720873243-6 .node polygon,#publish-mermaid-1785720873243-6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873243-6 .rough-node .label text,#publish-mermaid-1785720873243-6 .node .label text,#publish-mermaid-1785720873243-6 .image-shape .label,#publish-mermaid-1785720873243-6 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1785720873243-6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1785720873243-6 .rough-node .label,#publish-mermaid-1785720873243-6 .node .label,#publish-mermaid-1785720873243-6 .image-shape .label,#publish-mermaid-1785720873243-6 .icon-shape .label{text-align:center;}#publish-mermaid-1785720873243-6 .node.clickable{cursor:pointer;}#publish-mermaid-1785720873243-6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1785720873243-6 .arrowheadPath{fill:#333333;}#publish-mermaid-1785720873243-6 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1785720873243-6 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1785720873243-6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873243-6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873243-6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873243-6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1785720873243-6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1785720873243-6 .cluster text{fill:#333;}#publish-mermaid-1785720873243-6 .cluster span{color:#333;}#publish-mermaid-1785720873243-6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1785720873243-6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1785720873243-6 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1785720873243-6 .icon-shape,#publish-mermaid-1785720873243-6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873243-6 .icon-shape p,#publish-mermaid-1785720873243-6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1785720873243-6 .icon-shape .label rect,#publish-mermaid-1785720873243-6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873243-6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1785720873243-6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1785720873243-6 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1785720873243-6 [data-look=\”neo\”].node rect,#publish-mermaid-1785720873243-6 [data-look=\”neo\”].cluster rect,#publish-mermaid-1785720873243-6 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873243-6 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1785720873243-6 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873243-6 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873243-6 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1785720873243-6 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873243-6 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1785720873243-6 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873243-6 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873243-6 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    旧列表: A B C D

    新列表: B A D E

    按Key匹配

    A: 位置从0变1

    B: 位置从1变0

    C: 不存在删除

    D: 位置不变

    E: 新增

    移动A

    移动B

    删除C

    创建E

    Key的使用原则如下:

  • 使用唯一且稳定的值作为Key,如数据ID
  • 避免使用数组索引作为Key,因为索引在列表变化时会改变
  • 不要使用随机值作为Key,会导致每次渲染都无法复用
  • 正确使用Key的示例:

    // 正确: 使用唯一ID作为Key
    {items.map(item => (
    <li key={item.id}>{item.name}</li>
    ))}
    // 错误: 使用索引作为Key
    {items.map((item, index) => (
    <li key={index}>{item.name}</li>
    ))}

    六、实际开发中的选择建议

    6.1 何时选择真实DOM

    在以下情况下,直接操作真实DOM更为合适:

  • 页面极其简单,交互少,无需框架
  • 需要极致性能的简单操作,如Canvas动画、拖拽
  • 对包体积有严格限制,无法引入框架
  • 维护遗留jQuery项目
  • 开发原生Web Components
  • 6.2 何时选择虚拟DOM

    在以下情况下,使用虚拟DOM(通过React、Vue等框架)更为合适:

  • 构建中大型单页应用,UI复杂且交互频繁
  • 需要跨平台开发,如同时支持Web和移动端
  • 团队协作开发,需要声明式编程模式
  • 数据驱动UI,状态管理复杂
  • 需要服务端渲染(SSR)支持
  • 6.3 综合对比总结

    真实DOM与虚拟DOM的综合对比如下:

    #publish-mermaid-1785720873325-7{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#publish-mermaid-1785720873325-7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873325-7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#publish-mermaid-1785720873325-7 .error-icon{fill:#552222;}#publish-mermaid-1785720873325-7 .error-text{fill:#552222;stroke:#552222;}#publish-mermaid-1785720873325-7 .edge-thickness-normal{stroke-width:1px;}#publish-mermaid-1785720873325-7 .edge-thickness-thick{stroke-width:3.5px;}#publish-mermaid-1785720873325-7 .edge-pattern-solid{stroke-dasharray:0;}#publish-mermaid-1785720873325-7 .edge-thickness-invisible{stroke-width:0;fill:none;}#publish-mermaid-1785720873325-7 .edge-pattern-dashed{stroke-dasharray:3;}#publish-mermaid-1785720873325-7 .edge-pattern-dotted{stroke-dasharray:2;}#publish-mermaid-1785720873325-7 .marker{fill:#333333;stroke:#333333;}#publish-mermaid-1785720873325-7 .marker.cross{stroke:#333333;}#publish-mermaid-1785720873325-7 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#publish-mermaid-1785720873325-7 p{margin:0;}#publish-mermaid-1785720873325-7 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#publish-mermaid-1785720873325-7 .cluster-label text{fill:#333;}#publish-mermaid-1785720873325-7 .cluster-label span{color:#333;}#publish-mermaid-1785720873325-7 .cluster-label span p{background-color:transparent;}#publish-mermaid-1785720873325-7 .label text,#publish-mermaid-1785720873325-7 span{fill:#333;color:#333;}#publish-mermaid-1785720873325-7 .node rect,#publish-mermaid-1785720873325-7 .node circle,#publish-mermaid-1785720873325-7 .node ellipse,#publish-mermaid-1785720873325-7 .node polygon,#publish-mermaid-1785720873325-7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873325-7 .rough-node .label text,#publish-mermaid-1785720873325-7 .node .label text,#publish-mermaid-1785720873325-7 .image-shape .label,#publish-mermaid-1785720873325-7 .icon-shape .label{text-anchor:middle;}#publish-mermaid-1785720873325-7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#publish-mermaid-1785720873325-7 .rough-node .label,#publish-mermaid-1785720873325-7 .node .label,#publish-mermaid-1785720873325-7 .image-shape .label,#publish-mermaid-1785720873325-7 .icon-shape .label{text-align:center;}#publish-mermaid-1785720873325-7 .node.clickable{cursor:pointer;}#publish-mermaid-1785720873325-7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#publish-mermaid-1785720873325-7 .arrowheadPath{fill:#333333;}#publish-mermaid-1785720873325-7 .edgePath .path{stroke:#333333;stroke-width:1px;}#publish-mermaid-1785720873325-7 .flowchart-link{stroke:#333333;fill:none;}#publish-mermaid-1785720873325-7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873325-7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873325-7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873325-7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#publish-mermaid-1785720873325-7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#publish-mermaid-1785720873325-7 .cluster text{fill:#333;}#publish-mermaid-1785720873325-7 .cluster span{color:#333;}#publish-mermaid-1785720873325-7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#publish-mermaid-1785720873325-7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#publish-mermaid-1785720873325-7 rect.text{fill:none;stroke-width:0;}#publish-mermaid-1785720873325-7 .icon-shape,#publish-mermaid-1785720873325-7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#publish-mermaid-1785720873325-7 .icon-shape p,#publish-mermaid-1785720873325-7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#publish-mermaid-1785720873325-7 .icon-shape .label rect,#publish-mermaid-1785720873325-7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#publish-mermaid-1785720873325-7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#publish-mermaid-1785720873325-7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#publish-mermaid-1785720873325-7 .node .neo-node{stroke:#9370DB;}#publish-mermaid-1785720873325-7 [data-look=\”neo\”].node rect,#publish-mermaid-1785720873325-7 [data-look=\”neo\”].cluster rect,#publish-mermaid-1785720873325-7 [data-look=\”neo\”].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873325-7 [data-look=\”neo\”].swimlane.cluster rect{filter:none;}#publish-mermaid-1785720873325-7 [data-look=\”neo\”].node path{stroke:#9370DB;stroke-width:1px;}#publish-mermaid-1785720873325-7 [data-look=\”neo\”].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873325-7 [data-look=\”neo\”].node .neo-line path{stroke:#9370DB;filter:none;}#publish-mermaid-1785720873325-7 [data-look=\”neo\”].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873325-7 [data-look=\”neo\”].node circle .state-start{fill:#000000;}#publish-mermaid-1785720873325-7 [data-look=\”neo\”].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873325-7 [data-look=\”neo\”].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#publish-mermaid-1785720873325-7 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    真实DOM vs 虚拟DOM

    真实DOM

    虚拟DOM

    优点: 直接高效标准统一

    缺点: 频繁操作性能差跨平台受限

    适合: 简单页面原生开发

    优点: 批量优化跨平台声明式

    缺点: 首次渲染慢内存占用调试复杂

    适合: 复杂应用跨平台数据驱动

    核心对比表如下:

    | 维度 | 真实DOM | 虚拟DOM |

    |—–|———|———|

    | 本质 | 浏览器原生对象 | JavaScript对象 |

    | 创建成本 | 高 | 低 |

    | 操作方式 | 命令式 | 声明式 |

    | 性能(频繁更新) | 差 | 优 |

    | 性能(单次操作) | 优 | 略差 |

    | 跨平台 | 不支持 | 支持 |

    | 状态管理 | 手动 | 自动 |

    | 学习成本 | 低 | 中 |

    | 适用规模 | 小型 | 中大型 |

    总结来说,真实DOM是浏览器的基础设施,虚拟DOM是在其之上的抽象层与优化策略。两者并非替代关系,而是互补关系。在现代前端开发中,虚拟DOM通过Diff算法和批量更新机制,有效解决了真实DOM频繁操作的性能问题,同时带来了跨平台和声明式开发的优势。理解两者的区别与优缺点,有助于开发者在不同场景下做出合理的技术选型,写出高性能、可维护的前端代码。

    赞(0)
    未经允许不得转载:171主机测评 » 说说真实DOM和虚拟DOM的区别?它们的优缺点是什么?:深入理解前端渲染机制与性能优化之道
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址