react 面试题相关(一)

4 阅读8分钟

state 和 props的区别是什么

  • state 是组件自己管理数据,控制自己的状态,可变;
  • props 是外部传入的数据参数,不可变;
  • 没有state的叫做无状态组件,有state的叫做有状态组件;
  • 多用 props,少用 state,也就是多写无状态组件。

触发 React 重新渲染

  • setState 方法被调用时会触发重新渲染【注意点:setState设置为null时不一定会触发render】
  • 父组件重新渲染子组件会重新渲染

重新渲染 render 会进行什么操作

  • 进行vNode节点对比,diff算法
  • React 的处理 render 的基本思维模式是每次一有变动就会去重新渲染整个应用。在 Virtual DOM 没有出现之前,最简单的方法就是直接调用 innerHTML。Virtual DOM厉害的地方并不是说它比直接操作 DOM 快,而是说不管数据怎么变,都会尽量以最小的代价去更新 DOM。React 将 render 函数返回的虚拟 DOM 树与老的进行比较,从而确定 DOM 要不要更新、怎么更新。当 DOM 树很大时,遍历两棵树进行各种比对还是相当耗性能的,特别是在顶层 setState 一个微小的修改,默认会去遍历整棵树。尽管 React 使用高度优化的 Diff 算法,但是这个过程仍然会损耗性能.

什么时候应该使用类组件而不是函数组件? React组件错误捕获怎么做?

  • 从React16.8版本开始,几乎在所有场景下都可以使用函数组件替代类组件。
  • 有一个情况下,你可能还需要使用类组件,那就是错误边界(Eror Boundaries)。错误边界是React中的一种特性,它允许你在子组件树中捕获JavaScript错误并在发生错误时显示备用内容,而不是让整个组件树崩溃。错误边界在React中只能通过类组件来实现。

Hooks为什么不能写在条件判断、函数体里。我现在有业务场景就需要在if里写怎么办呢?

  • React Hooks 便用一个单向链表来保在组件的状态和副作用。在每次组件演染时,Read 会遍历这个链表,按照定义的顺序依次执行每个 Ho0k 对应的状态更新和副作用函数。通过链表的形式,React 可以保持 Hook 的调用顺序一致,并正确地跟踪每个 Hook 的状态和更新。
  • 使用组件外状态 zustand等

Dom Diff细节请详细描述一下?Vue使用了双指针,React为什么没采用呢?

  • React的更新过程包括 新旧虛拟DOM树的对比过程 和 更新DOM过程。 16版本之前,是 对比、更新 同时进行,对比的过程采用 递归 的方式,技术实现方式是不断的将各个节点、各个节点的子节点压入 栈 中,采用深度遍历的方式不断的访问子节点,回溯直到df完整棵树。整个过程由于是递归 实现的,中间不能中断、中断后必须要重新开始,如果树的层级较深,会导致整个更新过程(1s执行)时间过长,阻碍页面渲染和造成用户交互卡顿 等问题,体验较差。
  • 由于 递归算法、栈本身的局限性,16之后将 递归改成选代,而且只D(同层节点(div->span就不要了),并将 栈结构改进成fiber链表结构 ,实现了更新过程可以随时中断的功能。

React如何实现自身的事件系统?什么叫合成事件?

  • React合成事件(SyntheticEvent)是 React 框架自己实现的一套事件系统。这套系统模拟了原生的 DOM 事件,但同时提供了一些额外的优点:
    • 跨浏览器兼容性:不同浏览器的原生事件行为可能会存在差异。React 的合成事件为所有浏览器提供了一致的 AP!和行为,从而消除了这种差异。
    • 性能优化:React 使用了事件委托(even delegation)机制。这意味着对于同一类型的事件,React 并不会直接将事件处理器绑定到 DOM 节点上,而是将一个统2.一的事件监听器绑定到文档的根节点上,当事件发生时,React 会根据其内部映射确定真正的事件处理器,这样做可以有效减少事件临听器的教量、节省内存,提高性能。
    • 集成到 React 的状态系统:React合成事件系统与其组件生命周期和状态系统紧密集成,可以在事件处理函数中调用 selslate,React 会正确地批处理更新和重新渲染。
    • 提供更多的信息:React 的合成事件提供了比原生事件更多的信息,例如 event.target。合成事件的名称(例如 onCick,onchange 等)和它们在组件中的使用方式、都与你在 JavaScript 中使用 DOM 事件的方式非常相似。实际上,大多数情况下,你可以把它们当作标准的 DOM 事件来使用。
  • 在Reac组件中、对大多数事件来说,React 实际上并不会将它们附加到 DOM节点上。相反,React会直接在 document 节点上为每种事件类型附加一个处理器。除了在大型应用程序上具有性能优势外,它还使添加类似于replaying events 这样的新特性变得更加容易。
    • 但是如果页面上有多个 React 版本,他们都将在顶层注册事件处理器。这会破坏e.stoppropagation():如果嵌套树结构中阳止了事件冒泡,但外部树依然能接收到它。这会使不同版本 React 嵌套变得困难。
    • 在React 17中,React 将不再向 document 附加事件处理器。而会将事件处理器附加到渲染 React 树的根 DOM 容器中:

React Concurrent Mode是什么?React18是怎么实现的?他和useTransition有联系么?

  • React 的 Concurrent Mode是一种新的渲染模式,它使 React 能够在多个状态更新中进行“时间切片",从而使得长时间运行的渲染任务不会阻塞浏览器的主线程。这种模式可以提高应用的响应性,特别是在复杂的用户界面和/或设备性能较低的情况下,
  • 在传统的同步渲染模式中,React 会在一个状态更新发生时阳塞主线程,直到所有的组件都渲染完成。在一些情况下,这可能会导致应用变得不响应,因为主线程在渲染过程中无法处理其他任务,比如用户输入和动画,
  • 而在 Concurent Mode 中,React会把渲染任务分解成多个小任务,每个任务的执行时间都很短。在这些任务之间,React 会给出一些空闲的时间,让浏览器有机会处理其他的任务。这就是所谓的“时间切片"。
  • uselransition,是一个在 React 18 中引入的新的 Hook,它与 Concurent Mode 紧密相关。 useTrinsition 使你可以告诉 Reac 你的状态更新可能需要一些时间来准备数据,例如发起一个网络请求,在这个状态更新的数据准备好之前,React 会继续显示旧的 U1,而不是立即渲染一个加载的状态,这可以避免界面的抖动,提 高用户体验、
  • 在 Concurent Mode 中, useTransition 可以让你的应用在等待新的数据时保持响应,同时在数据准备好之后再平滑的过渡到新的状态。
  • 需要注意的是,Concurrent Mode 和 userransition 都是 React 18 中的新特性。

React Dom Diff原理

  1. 将 current 中所有同级 fiber保存在 mp中
  2. 遍历 newchild 数组,对于每个遍历到的 element ,存在两种情况:
  3. 在 yap 中存在对应 current fiber ,且可以复用"在 Map 中不存在对应 current fiber ,或不能复用
  4. 判断是插入还是移动
  5. 最后 nap 中剩下的都标记删除

同构注水脱水是什么意思?React 进行ServerLess渲染时候项目需要做哪些改变?

React同构渲染涉及到"注水"和“脱水"的概念,这两个术语来源于React服务器端渲染(SSR)的两个重要步骤。

  • 脱水(Dehydration):在服务器端,React将组件树渲染为HTML字符串,并生成与应用状态相关的数据(即“脱水"数据)。这个过程就被称为“脱水"。然后,服务器将渲染后的HTML和脱水数据一起发送到客户。
  • 注水(Rehvdration):在客户端,React使用服务器发送过来的脱水数据来恢复应用的状态,这个过程被称为"注水"。然后React会对服务器渲染的HTML和客户端组件树进行匹配,如果匹配成功,React将接管这些已经存在的DOM节点,使其变得可以交互。

这种同构渣染的方式有几个好处:首先、用户可以更早地看到页面内容,因为浏览器无需等待所有的JavaScrot代码下载和执,行完毕就可以显示服务器消染的HTMLH其次,由于服务器已经生成了初始状态,客户端无需再次获取教据;最后,React可以复用服务器道染的DOM:避免了额外的DOM操作,从而提高了性能。但需要注意,这种方式也有一些缺点,例如服务器端演染可能会增加服务器的负载,以及在注水过程中可能会出现一些问题,如数据不一致或者错误的状态等。