前端面试题之——React

一 面试题汇总

  1. 虚拟DOM的原理
  2. 简要介绍一下React组件的生命周期
  3. 简要介绍一下React中的refs以及它的作用
  4. 简要介绍一下key以及它的作用
  5. 在实际开发中shouldComponentUpdate有什么作用
  6. 简要介绍一下Redux
  7. setState的第二个参数是什么,作用又是什么?
  8. 简要介绍一下你所了解的flux架构的思想?
  9. 聊一聊你对React的DOM diff算法的理解
  10. 虚拟DOM的优缺点有哪些?

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

2.1 虚拟DOM的原理

1
2
3
4
5
6
我们知道前端的DOM是一棵树,对于一个element来说,我们需要关注的是这个element的 tagName、属性、以及子元素,
而这完全可以用一个js对象来表示,比如,使用tagName属性 来说明标签名,
将所有的属性和值作为一个对象表示为props,children属性来表示这个element的 子元素,
同样有了这个js对象,我们就可以构建一棵真实的DOM树,我们可以在每一次元素也就是js对象
有任何变动的时候来重新构造一棵树,将这棵新的树与旧的DOM数进行比对,找出真正差异的地方,
然后 将这些差异应用在真实的DOM中,也就实现了一个简单的Virtual DOM算法。

2.2 简要介绍一下React组件的生命周期

1
2
3
4
5
6
7
8
9
10
11
React的组件在第一次挂载的时候回首先获得父组件传递的props,接着获取初始的state值,
接着经历挂载 阶段的三个生命周期函数也就是ComponentWillMount、render、ComponentDidMount,
这三个函数 分别代表着组件将会挂载、组件渲染、组件挂载完毕三个阶段。

在组件挂载完成之后,组件的props和state的任一 改变都会导致组件进入更新状态,
在组件更新阶段如果是props改变,则进入ComponentWillReceiveProps函数,
接着进入ComponetShouldUpdate进行判定是否需要更新,
如果是state的改变则直接进入ComponentShouldUpdate 判定,这个默认是true,
当判定不需要更新的话,组件继续运行,需要更新则依次进入ComponentWillUpdate、render、 ComponentDidUpdate三个生命周期函数,
依次代表着组件将要更新、组件在渲染、组件更新完毕。当组件卸载时,
会首先 进入生命周期函数ComponentWillUnmount,之后才进行卸载

2.3 简要介绍一下React中的refs以及它的作用

1
2
3
4
ref允许我们访问DOM元素,我们通过在组件中指定ref属性,属性值为一个回调函数,
这个回调函数接受一个DOM元素或者react组件 作为参数,
当我们不得不要直接访问DOM元素的时候才去使用它,
如我需要在组件加载完成就立即让组件中的表单有焦点,即触发 focus事件

2.4 简要介绍一下key以及它的作用

1
2
3
4
在react中我们渲染一个列表的时候,我们需要为每一个列表项指定一个唯一的key,
当没有指定key时,会收到一个warning,
如果指定的key不唯一,只会渲染第一个指定唯一的key的那个元素,
使用key可以使得DOM diff更加高效,避免不必要的 列表项更新

2.5 在实际开发中shouldComponentUpdate有什么作用

1
2
3
4
5
6
7
8
9
10
11
在实际开发中,shouldComponentUpdate 方法在 React 组件中起着非常重要的作用。它用于控制组件的更新,决定当组件的 props 或 state 发生变化时是否重新渲染组件。shouldComponentUpdate 方法返回一个布尔值,如果返回 true,则表示组件将会重新渲染;如果返回 false,则表示组件将不会重新渲染。

shouldComponentUpdate 方法的作用主要体现在以下几个方面:

1-性能优化:在 React 应用中,组件的重新渲染可能会导致性能问题,特别是当组件的 props 或 state 发生变化时,如果不经过考虑地重新渲染组件,可能会导致不必要的重绘和性能损耗。通过实现 shouldComponentUpdate 方法,可以在组件更新之前进行判断,避免不必要的重新渲染,提高组件的性能和渲染效率。

2-避免不必要的渲染:在某些情况下,组件的 props 或 state 变化并不会影响组件的显示,此时重新渲染组件是没有必要的。通过实现 shouldComponentUpdate 方法,可以根据组件的 props 和 state 变化的情况,决定是否需要重新渲染组件,从而避免不必要的渲染,提高页面的性能和响应速度。

3-减少不必要的组件更新:在 React 应用中,某些情况下可能会导致大量组件的更新,例如在父组件的状态变化时,所有子组件都会重新渲染。通过在子组件中实现 shouldComponentUpdate 方法,可以根据具体情况来决定是否需要更新组件,从而减少不必要的组件更新,提高页面的性能。

总的来说,shouldComponentUpdate 方法在 React 组件中起着非常重要的作用,它可以帮助我们优化组件的性能,避免不必要的渲染,提高页面的性能和用户体验。在实际开发中,需要根据具体情况合理地实现 shouldComponentUpdate 方法,以达到性能优化的目的。

2.6 简要介绍一下Redux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Redux 是一个用于 JavaScript 应用程序的状态管理库,通常与 React 一起使用。它的设计目标是管理应用程序中的状态,并提供一种可预测的状态管理方式,使得应用程序的状态变化可追踪和可调试。

Redux 主要包含以下几个核心概念:

1-Store(仓库):存储应用程序的状态,并提供了一些方法来获取状态、修改状态以及订阅状态的变化。应用程序中只有一个 Store。

2-Action(动作):描述应用程序中发生的事件的纯 JavaScript 对象,通常包含一个 type 字段来表示动作的类型,以及可选的 payload 字段来携带数据。

3-Reducer(归纳器):描述状态如何根据动作来变化的纯函数。它接收当前状态和动作作为参数,并返回一个新的状态。应用程序中可能有多个 Reducer,每个 Reducer 负责管理状态的一部分。

4-Dispatch(分发):触发动作的方法,用于向 Store 发送动作。当调用 dispatch(action) 时,Store 将动作传递给 Reducer,从而更新状态。

5-Action Creator(动作创建器):用于创建动作的函数,通常返回一个描述动作的对象。Action Creator 可以帮助封装动作的创建过程,使代码更易读和易维护。

6-Middleware(中间件):位于 Action 被发送到 Reducer 之前的扩展点,可以在 Middleware 中进行一些额外的逻辑处理,例如异步操作、日志记录等。

2.7 setState的第二个参数是什么,作用又是什么?

1
setState的第二个参数是一个回调函数,组件更新完后执行的回调函数(setState函数是异步的)

2.8 简要介绍一下你所了解的flux架构的思想?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Flux 是一种用于构建用户界面的应用程序架构,由 Facebook 提出。它的核心思想是单向数据流,通过严格的数据流向来管理应用程序的状态,使得应用程序更易于理解、调试和维护。

Flux 架构的主要思想包括以下几个核心概念:

1-单向数据流:Flux 架构中数据流是单向的,数据从一个固定的入口进入系统,然后流经一系列的处理逻辑,最终被存储在一个单一的状态树中。视图组件从状态树中读取数据,并向外部发送动作来改变状态。

2-Action(动作):描述用户行为或系统事件的简单对象,通常包含一个动作类型(type)字段和可选的数据字段(payload)。动作用于描述应用程序中发生的事件,例如用户点击按钮、发送请求等。

3-Dispatcher(派发器):用于分发动作的中心机制,负责接收来自视图组件的动作,并将它们分发给注册的处理器(Stores)。Dispatcher 保证动作按照固定的顺序被处理,并保持对 Store 的弱引用,以避免循环依赖问题。

4-Store(存储):负责存储应用程序的状态和业务逻辑,并对外暴露状态的获取接口。Store 接收来自 Dispatcher 的动作,并根据动作类型来更新自身的状态。通常,应用程序中会存在多个 Store,每个 Store 管理自己的一部分状态。

5-View(视图):负责展示应用程序的用户界面,从 Store 中获取数据并将其呈现给用户。视图组件可以监听 Store 的变化,并在状态发生变化时重新渲染自身。

Flux 架构的优点包括清晰的数据流向、易于调试和测试、组件间解耦等。它的设计思想和单向数据流模式为构建大型复杂应用程序提供了一个可靠的架构模式。虽然 Flux 并不是一个具体的实现,而是一种设计思想,但有许多基于 Flux 架构的实现,如 Redux、Fluxible 等。

2.9 聊一聊你对React的DOM diff算法的理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
React 的 Virtual DOM 和 diff 算法是其核心工作原理之一,它们是 React 实现高效更新 UI 的关键。下面是我对 React DOM diff 算法的理解:

1-Virtual DOM:
React 通过构建虚拟 DOM 树来表示 UI 结构,即在内存中构建一颗树形结构来描述页面的结构。
虚拟 DOM 是 React 自定义的一种数据结构,用 JavaScript 对象表示真实 DOM 的层次结构。
虚拟 DOM 具有轻量、高效的特性,可以快速创建、比较和更新,同时可以在不同的平台上使用,例如浏览器端、服务器端等。
2-Diff 算法:
当状态发生变化时,React 会使用 diff 算法来比较前后两次虚拟 DOM 树的差异。
Diff 算法会逐层对比两棵树的节点,找出需要更新的部分,然后仅对需要更新的部分进行操作,从而实现高效的页面更新。
Diff 算法会尽量减少真实 DOM 的操作次数,以提高页面的性能和渲染效率。

3-Diff 算法的核心思想:
从根节点开始逐层对比,首先判断根节点是否相同,如果不同则直接替换整个子树。
如果根节点相同,则比较子节点,对子节点进行进一步比较。
对比子节点时,采用了三种策略:同层比较、双端比较和唯一 key 优化。
同层比较:将新旧节点列表按序比较,尽量复用已有的节点。
双端比较:在列表两端分别比较,优化了新增和删除节点的情况。
唯一 key 优化:通过唯一 key 来识别节点,加快对比速度和提高复用性。

4-Diff 算法的时间复杂度:
Diff 算法的时间复杂度是 O(n),其中 n 表示节点数目。因为它只需要遍历一次虚拟 DOM 树,然后根据节点的变化情况来更新真实 DOM。

2.10 虚拟DOM的优缺点有哪些?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
虚拟 DOM 技术是 React 等现代前端框架的核心特性之一,它带来了许多优点,但也存在一些缺点。下面是虚拟 DOM 的优缺点:

优点:

1-提高性能:虚拟 DOM 可以在内存中构建整个页面的抽象表示,然后通过 diff 算法找出真实 DOM 树和虚拟 DOM 树的差异,最终只更新真正发生变化的部分,从而减少了页面重绘的次数,提高了页面的性能。

2-跨平台使用:虚拟 DOM 不依赖于浏览器环境,可以在不同的平台上使用,例如浏览器端、服务器端、移动端等,提高了代码的可复用性和跨平台兼容性。

3-提高开发效率:虚拟 DOM 可以通过 JavaScript 对象来描述页面的结构,相比于直接操作 DOM 元素,它更加灵活和方便,可以通过代码来生成页面的结构,提高了开发效率。

4-优化渲染性能:虚拟 DOM 可以批量更新页面的变化,而不是一次性地更新每个变化,从而减少了页面渲染的次数,优化了渲染性能,提高了用户体验。

5-实现组件化开发:虚拟 DOM 技术可以很好地支持组件化开发,将页面拆分成多个独立的组件,每个组件都有自己的状态和 UI 表现,通过组合这些组件可以构建复杂的界面。

缺点:

11-内存消耗:虚拟 DOM 需要在内存中维护一份页面的抽象表示,因此会占用一定的内存空间,特别是对于大型页面或页面结构复杂的情况下,可能会增加内存消耗。

2-初始化耗时:虚拟 DOM 需要在页面初始化时构建整个页面的抽象表示,然后通过 diff 算法进行比较和更新,这个过程可能会消耗一定的时间,特别是对于页面结构较复杂的情况下,初始化耗时可能会比较长。

3-不利于 SEO:由于虚拟 DOM 是在客户端生成的,搜索引擎爬虫无法直接获取页面的内容,可能会影响页面的搜索引擎优化(SEO)效果。

4-学习成本:使用虚拟 DOM 技术需要一定的学习成本,开发人员需要了解虚拟 DOM 的工作原理和使用方式,以及相应的 diff 算法等,这可能会增加开发人员的学习成本和上手难度。

三 参考

  • FE-Interview—React