Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

面试官:说说 Real DOM和 Virtual DOM 的区别?优缺点? #181

Open
huihuiha opened this issue Jul 5, 2021 · 13 comments
Open

Comments

@huihuiha
Copy link
Contributor

huihuiha commented Jul 5, 2021

一、是什么

Real DOM,真实DOM, 意思为文档对象模型,是一个结构化文本的抽象,在页面渲染出的每一个结点都是一个真实DOM结构,如下:

Virtual Dom,本质上是以 JavaScript 对象形式存在的对 DOM 的描述

创建虚拟DOM目的就是为了更好将虚拟的节点渲染到页面视图中,虚拟DOM对象的节点与真实DOM的属性一一照应

React中,JSX是其一大特性,可以让你在JS中通过使用XML的方式去直接声明界面的DOM结构

const vDom = <h1>Hello World</h1> // 创建h1标签,右边千万不能加引号
const root = document.getElementById('root') // 找到<div id="root"></div>节点
ReactDOM.render(vDom, root) // 把创建的h1标签渲染到root节点上

上述中,ReactDOM.render()用于将你创建好的虚拟DOM节点插入到某个真实节点上,并渲染到页面上

JSX实际是一种语法糖,在使用过程中会被babel进行编译转化成JS代码,上述VDOM转化为如下:

const vDom = React.createElement(
  'h1' 
  { className: 'hClass', id: 'hId' },
  'hello world'
)

可以看到,JSX就是为了简化直接调用React.createElement() 方法:

  • 第一个参数是标签名,例如h1、span、table...

  • 第二个参数是个对象,里面存着标签的一些属性,例如id、class等

    第三个参数是节点中的文本

通过console.log(VDOM),则能够得到虚拟VDOM消息

所以可以得到,JSX通过babel的方式转化成React.createElement执行,返回值是一个对象,也就是虚拟DOM

二、区别

两者的区别如下:

  • 虚拟DOM不会进行排版与重绘操作,而真实DOM会频繁重排与重绘
  • 虚拟DOM的总损耗是“虚拟DOM增删改+真实DOM差异增删改+排版与重绘”,真实DOM的总损耗是“真实DOM完全增删改+排版与重绘”

以前文章举过的例子:

传统的原生apijQuery去操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程

当你在一次操作时,需要更新10个DOM节点,浏览器没这么智能,收到第一个更新DOM请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程

而通过VNode,同样更新10个DOM节点,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性attachDOM树上,避免大量的无谓计算

三、优缺点

真实DOM的优势:

  • 易用

缺点:

  • 效率低,解析速度慢,内存占用量过高
  • 性能差:频繁操作真实DOM,易于导致重绘与回流

使用虚拟DOM的优势如下:

  • 简单方便:如果使用手动操作真实DOM来完成页面,繁琐又容易出错,在大规模应用下维护起来也很困难

  • 性能方面:使用Virtual DOM,能够有效避免真实DOM数频繁更新,减少多次引起重绘与回流,提高性能

  • 跨平台:React借助虚拟DOM, 带来了跨平台的能力,一套代码多端运行

缺点:

  • 在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化
  • 首次渲染大量DOM时,由于多了一层虚拟DOM的计算,速度比正常稍慢

参考文献

@Aloha-xu
Copy link

你好,请问一下,’最终将这个js对象一次性attach到DOM树上‘ , 这句话 不是很理解。
具体是怎么操作的?

@ZZZWTGitHub
Copy link

Update the DOM tree all change in once

@Grace-zx
Copy link

请问一下这句话怎么理解:React借助虚拟DOM, 带来了跨平台的能力,一套代码多端运行

@Aloha-xu
Copy link

请问一下这句话怎么理解:React借助虚拟DOM, 带来了跨平台的能力,一套代码多端运行
就是把dom转为js对象的形式来体现dom树,这个js对象是可以转化为不同端的具体真实Dom的。

@tiny-dust
Copy link

请问一下这句话怎么理解:React借助虚拟DOM, 带来了跨平台的能力,一套代码多端运行

简单的理解就是 虚拟dom实际上是一个结构固定的js对象,借助自定义的babel转换成对应的东西,比如在type="div" 加载到html里可以转成div 在小程序你可以转成view。

@insistenceZHUO
Copy link

真实dom 效率低,解析速度慢,内存占用量过高。 这个怎么理解???

@YolandaFeng2022
Copy link

请问一下这句话怎么理解:React借助虚拟DOM, 带来了跨平台的能力,一套代码多端运行

同问

@MoXiaoluo
Copy link

请问一下这句话怎么理解:React借助虚拟DOM, 带来了跨平台的能力,一套代码多端运行

同问

react的虚拟dom用到了移动端,网页端,服务端。

@MoXiaoluo
Copy link

真实dom 效率低,解析速度慢,内存占用量过高。 这个怎么理解???

如果单论操作一次真实dom的过程,原生的肯定比react执行的快,毕竟原生的没有执行虚拟dom这一层操作,但是如果操作多次的话,原生的需要频繁的查询dom,这是比较费时间的,采用虚拟dom的话,更新的过程是很快的,然后一次性的添加到页面里面。

@pengzhanbo
Copy link

这里的 优缺点描述有误导性。

Real DOM 和 Virtual DOM 的对比,需要在其应用场景中来对比的。

如果仅仅是 对DOM的一次修改,或者 低频次的,低复杂度的 修改,那么 Real DOM 的 性能肯定是要高于 Virtual DOM 的。

而如果是 复杂场景,需要频繁的,高频次的修改, 那么 Virtual DOM 就可以提供 一种相对于 DOM tree 更简单的 对象树结构 来描述 Real DOM,为 复杂场景 的 DOM 更新提供 基础支持,可以在基于 Virtual DOM 的基础上采用 Diff 算法,收集在某一段时间内的需要更新的DOM,将 复杂场景下可能存在的 频繁修改整个DOM Tree 带来的性能开销 优化为 集中更新需要修改的DOM,从而从整体上带来 性能提升。
而效率是否高效,这个要结合怎么去用 Virtual DOM 的,比如 React, 比如 Vue,是 它们 对比 Real DOM 使我们的效率得到了提升。

@Volcano-Yang
Copy link

Volcano-Yang commented Sep 8, 2023

虚拟DOM不会进行排版与重绘操作,而真实DOM会频繁重排与重绘

这段话的频繁触发重排与重绘,最好说成频繁触发重排或重绘。因为不是所有操作都会触发重排。

@clarencesea
Copy link

请问一下这句话怎么理解:React借助虚拟DOM, 带来了跨平台的能力,一套代码多端运行

虚拟dom就是js对象,可以被解释成android和ios或其他端的组件或代码

@flxy1028
Copy link

flxy1028 commented May 1, 2024

同志们不要误导人了,虚拟dom不会比直接操作dom快, 它的最有用的部分是跨平台能力,虚拟dom 处理后最后还是操作dom,所以不可能比直接操作dom快,平时说的比真实dom快,可以理解为可以减少不必要的dom操作,从而可提升性能。通过虚拟dom的diff算法减少不必要的dom操作,用js性能换dom操作的性能, 因为dom操作是一个性能很不好的操作,可以理解为 dom操作很慢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests