前端面试题—面试题整理(2)

一 面试题汇总(Boss直聘分享-胜天网络和东高科技)

  1. 原型和原型链
  2. webpack的构建流程
  3. 说说轮播图的思路
  4. redux的工作流程
  5. http缓存有哪些
  6. websocket的底层协议
  7. vue2和vue3的tree shaking的区别
  8. 为什么要减少http的请求
  9. vue的双向数据绑定的原理
  10. 前端性能优化
  11. 事件循环
  12. 箭头函数
  13. react中组件传值
  14. 虚拟dom的原理

二 面试题解答(仅供参考)

2.1 原型和原型链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
原型(Prototype)和原型链(Prototype Chain)是 JavaScript 中重要的概念,
它们是实现继承和对象属性访问的基础。下面分别介绍一下这两个概念:

1. 原型(Prototype):
1.1-在 JavaScript 中,每个对象都有一个原型(prototype)属性,
它指向另一个对象,该对象称为原型对象(prototype object)。
1.2-对象的原型对象可以包含属性和方法,如果在当前对象上无法找到某个属性或方法,
JavaScript 引擎会沿着原型链查找,直到找到为止。
1.3-使用原型可以实现对象之间的共享属性和方法,从而节省内存空间和提高性能。
1.4-可以通过 Object.getPrototypeOf(obj) 方法或者 __proto__ 属性来访问对象的原型。

2. 原型链(Prototype Chain):

2.1-在JavaScript中,每个对象都有一个原型链(prototype chain),它是由对象的原型组成的一个链式结构。
2.2-当访问对象的属性或方法时,如果对象本身没有定义,则会沿着原型链向上查找,直到找到为止。
2.3-原型链的顶端是 Object.prototype,它是JavaScript中所有对象的根对象,
包含了一些基本方法和属性,如 toString()、valueOf() 等。
2.4-除了 Object.prototype,还可以通过原型链继续向上查找,直到找到null,这样就形成了一个完整的原型链。

综上所述,原型和原型链是 JavaScript 中实现继承和属性访问的核心机制,
它们通过对象之间的原型关联实现了对象的属性和方法的共享,并且提供了一种灵活和高效的继承方式。
理解原型和原型链对于理解 JavaScript 的面向对象编程是非常重要的。

2.2 webpack的构建流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Webpack 的构建流程可以简单概括为以下几个步骤:

1-解析配置文件:
Webpack 首先会解析项目根目录下的配置文件(通常是 webpack.config.js),获取其中的配置选项。

2-解析入口文件:
根据配置中的入口点(entry),Webpack 从入口文件开始分析项目的依赖关系。
通过解析入口文件及其依赖,Webpack 构建出一个依赖图(dependency graph)。

3-加载 Loader:
在解析文件时,Webpack 会根据配置中的 Loader 来处理不同类型的文件。
Loader 可以对文件进行转换、编译、压缩等操作,如将 ES6+ 代码转换为 ES5、处理 CSS、处理图片等。

4-解析模块:
Webpack 会根据依赖图,递归地解析项目中的所有模块,并根据配置中的别名(alias)等选项进行路径解析。
解析模块的过程中,Webpack 还会处理动态导入(dynamic import)等特殊情况。

5-执行插件:
在构建过程中的不同阶段,Webpack 会执行一系列插件(plugins)来完成各种任务,如优化、压缩、打包分析等。
插件可以根据需要在构建过程中对模块和资源进行修改、增强或优化。

6-生成输出文件:
最后,Webpack 根据入口点、依赖图和经过处理的模块,生成打包后的输出文件。
输出文件可以是单个或多个 bundle,可以是 JavaScript 文件、CSS 文件、图片文件等。

7-输出结果:
Webpack 将打包后的输出文件写入到指定的输出目录中,以供部署或发布使用。
输出目录和文件名可以通过配置文件中的 output 字段来指定。

总的来说,Webpack 的构建流程是一个将模块转换、打包和输出的过程,通过解析入口文件和依赖图,
应用 Loader 和插件,最终生成优化后的静态资源文件,以提高应用程序的性能和加载速度。

2.3 说说轮播图的思路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
轮播图是一个常见的前端组件,用于在页面上展示多张图片或内容,并以轮播的形式循环播放。
下面是一个简单的轮播图的实现思路:

1-HTML 结构:

在 HTML 中创建一个容器元素,用于包裹轮播图的内容。可以是 <div> 或 <ul> 等元素。
在容器元素内部创建多个轮播项(每张图片或内容对应一个轮播项),可以使用 <div> 或 <li> 等元素。

2-CSS 样式:

设置容器元素的宽度和高度,以及样式属性,如背景色、边框等。
设置轮播项的样式,如宽度、高度、定位等,以及过渡效果和动画效果的样式。

3-JavaScript 实现:

获取容器元素和轮播项的 DOM 元素。
设定一个计时器,定时切换轮播项的显示内容。
在计时器中,切换轮播项的显示内容,可以通过修改轮播项的样式来实现。
可以添加鼠标移入、移出事件,暂停或恢复轮播,以及添加前进、后退按钮,手动控制轮播的切换。

4-自动轮播:

使用 JavaScript 中的 setInterval() 函数来定时切换轮播项。
在计时器中,依次显示每个轮播项,切换间隔时间由开发者设定。

5-手动控制:

可以添加前进、后退按钮,通过点击按钮来手动切换轮播项。
也可以添加鼠标移入、移出事件,当鼠标移入时暂停轮播,移出时恢复轮播。

6-循环播放:

在轮播到最后一张时,切换到第一张轮播项,实现循环播放的效果。

7-响应式设计:

考虑不同屏幕尺寸下的显示效果,可以使用媒体查询或 JavaScript 来实现响应式设计,使轮播图在不同设备上显示效果良好。

综上所述,轮播图的实现思路是通过HTML结构、CSS样式和JavaScript动态效果来实现图片或内容的轮播显示,
可以根据需求添加自动播放、手动控制、循环播放等功能,以及响应式设计,使轮播图具有更好的用户体验。

2.4 redux的工作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Redux 是一个用于 JavaScript 应用程序状态管理的库,它遵循单向数据流的思想,
其工作流程可以简要概括如下:

1-Action 的触发:

应用程序中的某个组件通过调用 dispatch(action) 方法触发一个 action。
Action是一个简单的 JavaScript对象,其中包含了描述事件的类型(type)和传递给reducer 的数据。

2-Reducer 的处理:
Reducer 是一个纯函数,接收当前状态(state)和 action 作为参数,返回新的状态。
当一个 action 被触发时,Redux 调用每个注册的 reducer,传递当前状态和 action,并根据 reducer 返回的新状态更新应用程序的状态。

3-状态的更新:
Redux 根据 reducer 返回的新状态更新应用程序的状态。
如果有多个 reducer,Redux 会将它们的返回值合并成一个状态树(state tree)。

4-订阅状态变化:
在 Redux 中,可以通过 store.subscribe(listener) 方法来订阅状态的变化。
当状态发生变化时,Redux 调用订阅的监听函数(listener),通知应用程序状态发生了改变。

5-更新 UI:
应用程序中的 UI 组件通过订阅状态变化,在状态发生变化时自动更新视图。
当状态发生变化时,Redux 会触发 UI 组件的重新渲染,以反映最新的状态。

这就是 Redux 的基本工作流程:通过 action 触发事件,reducers 处理事件并更新状态,
状态变化时通知订阅者更新 UI。
这种单向数据流的架构使得应用程序的状态管理变得清晰可控,便于调试和维护。

2.5 http缓存有哪些

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
HTTP 缓存是通过在客户端(浏览器)和服务器之间缓存资源的机制,以提高 Web 页面的加载速度和性能。
HTTP 缓存主要分为以下几种类型:

1-浏览器缓存:

1.1-强缓存(Expires 和 Cache-Control):
通过设置 Expires或Cache-Control响应头来指定资源的过期时间,浏览器在缓存资源未过期前不会再次请求服务器。
1.2-协商缓存(Last-Modified 和 If-Modified-Since、ETag 和 If-None-Match):
在资源过期后,浏览器会发送一个请求到服务器,服务器会检查资源的修改时间(Last-Modified)或唯一标识符(ETag),
如果资源未发生变化,服务器返回 304 状态码,告知浏览器直接使用缓存。

2-代理服务器缓存:

代理服务器(如 CDN)也可以缓存 HTTP 响应,以减轻原始服务器的负载和提高访问速度。
代理服务器缓存的策略和机制类似于浏览器缓存,也包括强缓存和协商缓存。

3-HTML5 应用缓存:

HTML5 提供了应用程序缓存(Application Cache)机制,允许 Web 应用将页面资源缓存在客户端,以便在离线状态下访问。

4-Service Worker 缓存:

Service Worker 是运行在浏览器背后的一种脚本,可以拦截网络请求,并且可以缓存网络资源,实现离线访问、网络性能优化等功能。

5-HTTP/2 的 Server Push:

在 HTTP/2 中,服务器可以主动将资源推送给客户端,无需客户端发出请求。
这种机制可以减少客户端请求资源的次数,提高加载速度。

综上所述,HTTP 缓存是通过在客户端和服务器之间缓存资源的机制,
包括浏览器缓存、代理服务器缓存、HTML5 应用缓存、Service Worker 缓存等,
以提高 Web 页面的加载速度和性能。
不同类型的缓存机制可以根据具体的需求和场景选择合适的方式来进行优化。

2.6 websocket的底层协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
WebSocket 是一种基于 TCP 协议的全双工通信协议,
它在 HTTP 协议上建立了一个持久的连接,使得客户端和服务器之间可以进行双向通信。
WebSocket 协议在握手阶段使用了 HTTP 协议,但之后就不再遵循 HTTP 协议的规范,而是建立了自己的通信协议。

WebSocket 协议的特点包括:

1-全双工通信:客户端和服务器之间可以同时进行双向通信,任意一方可以主动发送消息给另一方。

2-持久连接:与传统的 HTTP 请求不同,WebSocket 建立的连接是持久性的,
连接一旦建立就保持活跃状态,不需要每次通信都重新建立连接。

3-较低的开销:WebSocket 协议的握手过程相对较轻量,且在建立连接后,
通信过程中只需要发送较小的帧头信息,相比于 HTTP 请求,通信开销更小。

4-双向通信:WebSocket 协议支持双向通信,不仅客户端可以向服务器发送消息,
服务器也可以主动向客户端发送消息,实现实时的推送功能。

WebSocket 协议在握手阶段使用了 HTTP 协议来升级连接,然后建立了一个持久的 TCP 连接。
在建立连接后,双方可以自由地进行通信,发送消息的格式遵循一定的协议规范,
通常是以帧的形式发送,帧中包含了消息的内容、类型、长度等信息。

总的来说,WebSocket 是一种基于 TCP 的全双工通信协议,
它在 HTTP 协议上建立了一个持久的连接,使得客户端和服务器之间可以进行双向通信,
是实现实时性数据交互的一种重要技术。

2.7 vue2和vue3的tree shaking的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
在 Vue 2 和 Vue 3 中,都支持 tree shaking,但在实现上有一些区别。

1-Vue 2 中的 Tree Shaking:

在 Vue 2 中,由于 Vue.js 采用了 UMD 模块格式,
它会导出一个包含了所有功能的完整构建(Full Build)和一个包含了运行时的轻量构建(Runtime-only Build)。
当使用 Vue 2 的时候,如果你使用的是完整构建,那么无论你的应用程序是否使用到了所有的功能,
最终打包出来的文件中都会包含完整的 Vue 功能。
如果你使用的是运行时构建,那么 Vue 2 会根据你的代码中实际使用的功能进行 tree shaking,
只打包进去你实际使用到的部分。

2-Vue 3 中的 Tree Shaking:
在 Vue 3 中,不再区分完整构建和运行时构建,而是采用了 ESM 模块格式。
Vue 3 的所有模块都以 ESM 格式导出。
ESM 格式的模块非常适合 tree shaking,因为它允许静态分析和优化。
在Vue 3 中,当你导入一个Vue组件时,只会引入组件中实际使用到的代码,
未被使用的代码不会被打包进最终的 bundle 中。

综上所述,Vue 3 使用 ESM 模块格式,并且支持更好的 tree shaking,
只会打包进去实际被使用到的代码,而不会打包未被使用的代码。
这使得 Vue 3 更加轻量、高效,同时也提高了应用程序的性能。

2.8 为什么要减少http的请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
减少 HTTP 请求是提高网页性能和用户体验的重要策略之一,主要原因包括以下几点:

1-减少加载时间:
每个 HTTP 请求都需要建立连接、发送请求、等待响应和接收数据等步骤,这些过程都会增加页面加载时间。
因此,减少 HTTP 请求可以减少页面加载时间,提高页面的加载速度。

2-减少带宽消耗:
每个HTTP请求都会占用一定的带宽资源,尤其是对于移动设备用户或者网络条件较差的用户来说,
带宽资源可能会更加宝贵。减少 HTTP 请求可以降低带宽消耗,减少用户的流量费用。

3-降低服务器压力:
每个 HTTP 请求都会给服务器带来一定的负载压力,尤其是在高并发情况下,大量的 HTTP 请求可能会导致服
务器性能下降或者服务中断。减少 HTTP 请求可以降低服务器的负载压力,提高服务器的稳定性和可靠性。

4-减少 DNS 查询时间:
每个 HTTP 请求都需要进行 DNS 查询,以解析域名对应的 IP 地址。
减少 HTTP 请求可以减少 DNS 查询次数,降低 DNS 查询的时间开销,提高页面的加载速度。

5-减少并行连接数量:
每个浏览器都有并行连接数的限制,过多的 HTTP 请求可能会导致连接池被耗尽,影响页面的加载速度。
减少 HTTP 请求可以降低并行连接数量,避免连接池被耗尽的情况发生。

综上所述,减少 HTTP 请求是提高网页性能、节约带宽资源、降低服务器压力和提升用户体验的重要措施。
通过合并和优化资源、使用缓存和CDN、减少不必要的请求等方法,
可以有效地减少 HTTP 请求,提高网页加载速度和性能。

2.9 vue的双向数据绑定的原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Vue.js 的双向数据绑定是其核心特性之一,它使得视图和模型之间的数据同步变得简单而高效。
Vue 的双向数据绑定原理可以分为以下几个步骤:

1-数据劫持(Data Observation):

当创建 Vue 实例时,Vue 会遍历传入的数据对象(通常是 data 对象)的属性,
使用 Object.defineProperty() 方法将每个属性转化为 getter/setter,
并在数据属性被访问和修改时触发相应的操作。
通过数据劫持,Vue 能够追踪属性的变化,并在属性被修改时触发响应的更新。

2-模板解析(Template Compilation):

Vue 会解析模板中的指令和插值表达式,如 {{}} 和 v-model 等。
当 Vue 实例的数据发生变化时,模板中绑定的数据会被重新渲染到视图上。

3-绑定更新(Binding Update):

在数据发生变化时,Vue 会通过数据劫持中的 setter 方法触发更新,进而更新模板中对应的视图。
如果是表单元素上的 v-model 指令,双向绑定会监听元素的 input 事件,
当用户输入内容时,将输入的值同步到数据模型中。

4-DOM 更新(DOM Manipulation):

当数据发生变化并且触发了更新时,Vue 会根据虚拟 DOM(Virtual DOM)算法比较新旧节点差异,
然后将差异部分更新到真实的 DOM 上,实现视图的更新。

Vue 通过对比新旧节点,仅更新发生变化的部分,避免了整个视图的重新渲染,从而提高了性能。

综上所述,Vue 的双向数据绑定原理是通过数据劫持和模板解析实现的,
在数据发生变化时,通过绑定更新和 DOM 更新将变化同步到视图中,从而实现了视图和模型之间的双向数据同步。
这种机制使得开发者可以更加便捷地管理和操作数据,提高了开发效率和用户体验。

2.10 前端性能优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
前端性能优化是提高网页加载速度、提升用户体验的重要手段之一。下面列举了一些常见的前端性能优化技巧:

1-减少 HTTP 请求:

合并和压缩 CSS、JavaScript 文件,减少 HTTP 请求次数。
使用 CSS Sprites 技术将多个小图片合并成一张大图,减少图片请求次数。
使用图标字体或 SVG 替代小图标,减少图像文件的请求。

2-优化资源加载:

使用 CDN 加速静态资源的加载。
将静态资源放置在不同的域名下,以增加浏览器并行下载资源的数量。
使用预加载和懒加载技术,提前加载或延迟加载页面所需资源。

3-优化 CSS 和 JavaScript:

删除无用的 CSS 和 JavaScript 代码。
将 JavaScript 放置在页面底部,或者使用 defer 和 async 属性延迟脚本加载。
使用 Webpack、Parcel 等构建工具进行代码压缩、代码分割等优化。

4-优化图片:

使用适当的图片格式,如 JPEG、PNG、WebP 等。
对图片进行压缩,减小图片文件的大小。
使用图片的 srcset 属性提供不同分辨率的图片,以适配不同设备。

5-使用缓存:

使用浏览器缓存来存储静态资源,减少重复下载。
使用 HTTP 缓存头(Cache-Control、Expires 等)来控制缓存策略。

6-减少重绘和重排:

避免频繁操作 DOM,尽量减少 JavaScript 对 DOM 的操作。
使用 CSS3 动画代替 JavaScript 动画,使用 transform 和 opacity 属性实现动画效果。

7-优化移动端性能:

使用 CSS3 动画代替 JavaScript 动画,以减少页面的 CPU 消耗。
使用 Touch 事件代替 Mouse 事件,提高移动设备的响应速度。

8-代码优化:

优化 JavaScript 代码,避免使用过多的全局变量和闭包。
使用事件委托来减少事件处理函数的数量。
使用 Web Workers 来将一些计算密集型的任务放在后台线程中执行。

9-监控和优化性能:

使用性能分析工具,如 Chrome DevTools、Lighthouse 等来分析页面加载性能。
使用监控工具来监控页面性能,及时发现和解决性能问题。

综上所述,前端性能优化涉及到多个方面,包括减少 HTTP 请求、优化资源加载、
优化 CSS 和 JavaScript、优化图片、使用缓存、减少重绘和重排、优化移动端性能、代码优化等。
通过合理使用这些优化技巧,可以有效提高网页加载速度、提升用户体验。

2.11 事件循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
事件循环(Event Loop)是 JavaScript 引擎中用来处理异步任务的一种机制,
它负责管理 JavaScript 代码的执行顺序,确保代码能够以非阻塞(non-blocking)的方式执行。

JavaScript 是单线程的,即在同一时间只能执行一个任务,但它支持异步编程,
即能够处理一些需要等待的任务,如网络请求、定时器等。
事件循环就是负责协调这些异步任务的执行顺序的机制。

事件循环的基本原理如下:

1-调用栈(Call Stack):

JavaScript 引擎通过调用栈来管理代码的执行顺序。
当一个函数被调用时,会被推入调用栈中,当函数执行完成后,会被弹出调用栈。

2-任务队列(Task Queue):

JavaScript 运行环境中存在多个任务队列,用来存放不同类型的任务。
常见的任务队列包括宏任务队列(macrotask queue)和微任务队列(microtask queue)。

宏任务队列用来存放一些需要等待较长时间的任务,如 setTimeout、setInterval、I/O 操作等。

微任务队列用来存放一些需要立即执行的任务,如Promise的then方法、MutationObserver的回调函数等。

3-事件循环:

当调用栈为空时,事件循环会不断地从任务队列中取出任务,放入调用栈中执行。
首先会检查微任务队列,如果微任务队列不为空,则依次执行微任务队列中的任务,直到微任务队列为空。
然后会从宏任务队列中取出一个任务执行,执行完成后再次检查微任务队列,依次执行微任务队列中的任务。
事件循环会不断地循环执行这个过程,直到所有任务都被执行完毕。

4-渲染:

在浏览器环境中,事件循环的执行过程中还会涉及到渲染进程,
即浏览器会在合适的时机将 DOM 更新到页面上,从而保持页面的响应性。

综上所述,事件循环是 JavaScript 引擎中用来处理异步任务的一种机制,
它通过调用栈、任务队列和事件循环等组件协同工作,确保 JavaScript 代码能够以非阻塞的方式执行。

2.12 箭头函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
箭头函数是 ES6 中新增的一种函数表达式语法,它提供了一种更简洁的方式来定义函数,
并且在语法上与传统的函数表达式有一些不同之处。

箭头函数的基本语法如下:

const myFunction = (param1, param2) => {
// 函数体
};

箭头函数的特点包括:

1-更简洁的语法:箭头函数的语法更加简洁清晰,
省略了function 关键字和大括号(如果函数体只有一条语句则可以省略大括号),使得代码更加精简易读。

2-词法作用域:箭头函数不会创建自己的 this、arguments、super 和 new.target,
它们会继承父作用域中的相应值。这意味着箭头函数的 this 是在定义时确定的,
而不是在执行时确定的,称为词法作用域。

3-无法作为构造函数:箭头函数不能使用new关键字调用,也不能作为构造函数使用,因为它没有自己的this 值。

4-不能使用 arguments 对象:箭头函数没有自己的arguments对象,如果需要使用函数参数,可以通过 rest 参数来获取。

5-没有原型:箭头函数没有 prototype 属性。

6-没有 arguments,super,new.target 绑定:
箭头函数在创建时绑定了外层函数的 arguments、super、new.target,它们在箭头函数内部无法访问。

箭头函数通常适用于需要更简洁的函数定义,以及需要保持词法作用域的场景。
但在某些情况下,传统的函数表达式可能更适合,特别是在需要使用 this 或 arguments 的场景中。

2.13 react中组件传值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在 React 中,组件之间的值传递通常通过 props 属性来实现。下面是一些常见的组件传值方式:

1-父组件向子组件传值:

父组件可以通过在子组件上设置属性(props)来传递值给子组件。
子组件可以通过 this.props 来访问这些属性。

2-子组件向父组件传值:

子组件可以通过在父组件传递一个回调函数,并在合适的时机调用这个回调函数来传值给父组件。


3-兄弟组件之间传值:

如果两个组件之间没有直接的父子关系,可以使用共享的父组件来传递值。

这些是React中常见的组件传值方式,通过props属性和回调函数,可以实现组件之间的数据传递和通信。

2.14 虚拟dom的原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
虚拟 DOM(Virtual DOM)是 React 中的一种优化技术,
它通过在内存中维护一颗以JavaScript对象表示的虚拟DOM树,然后将虚拟DOM与真实DOM进行比对,
最终只更新发生变化的部分,从而提高页面渲染性能。

虚拟 DOM 的基本原理如下:

1-初始渲染:

当组件首次渲染时,React 会根据组件的 JSX 代码构建一个虚拟 DOM 树。
虚拟 DOM 树是一个以 JavaScript 对象表示的树形结构,包含了组件的元素、属性和子元素等信息。

2-更新操作:

当组件状态发生变化或者 props 发生变化时,React 会重新构建一个新的虚拟 DOM 树。
React 会将新的虚拟 DOM 树与之前的虚拟 DOM 树进行比较,找出两者之间的差异。
这个过程称为协调(Reconciliation),React会尽可能地高效地找出最小的更新单位,从而减少DOM操作次数。

3-批量更新:

React 会将需要更新的内容进行批量处理,减少不必要的 DOM 操作,提高性能。
React 会将需要更新的内容放入一个队列中,在合适的时机统一进行更新。

4-渲染到真实 DOM:

最后,React 将更新后的虚拟 DOM 树渲染到真实的 DOM 中。
React 使用 diff 算法来比较新旧虚拟 DOM 树的差异,找出需要更新的部分。

通过使用虚拟 DOM,React 实现了对页面的高效更新,减少了不必要的 DOM 操作,提高了页面渲染性能。
虽然构建和比较虚拟 DOM 树也会消耗一定的性能,
但相比直接操作真实 DOM,虚拟 DOM 的优势更加明显,尤其在需要频繁更新页面内容的场景下。

三 参考

  • ChatGPT3.5