React常见面试题
带着问题阅读《React 设计原理》一书时,总结常见面试题,方便快速复习
1、当前主流的两种描述 UI 的方案
- 方案1 JSX:核心是扩展ES(ECMScript)语法,使它能够描述UI(React)
- JSX本质 是Facebook/Meta 提出的类XML语法的ECMScript语法糖
- 方案2 模板语法:核心是扩展HTML,使它能够描述逻辑(Vue)
2、副作用定义
函数调用过程中掺杂的外部可观察的变化 - 是函数式编程的概念
3、React 常见 hooks 作用
useState:定义组件内部的自变量
useReducer:UseState本质是内置 render 的 useReducer,useReducer 也相当于组件内部定义的自变量
useContext:是 React 中 store 的实现,用于跨层级讲其他组件的自变量传递给当前组件
useMemo:采用“缓存的方式”定义组件内部的“无副作用因变量”
useCallback:采用“缓存的方式”定义组件内部的“无副作用因变量”,缓存的值为函数形式
useEffect:定义组件内部“有副作用的因变量”
useRef:用于在组件多次 render 之间缓存一个“引用类型的值”
4、React为什么不使用预编译
- 方式1 JSX:对 “ JSX描述UI ” 的框架收益少,因为ES 的灵活性太高,难以解析(React)
- 方式2 模版语法:对 “模版语法描述 UI” 的框架,提升收益大(例如Vue3对静态、动态节点的分析,跳过)
5、前端框架的实现原理
框架比较 | 原理(原理图如上) | 变量追踪 | 更新 |
---|---|---|---|
Vue3 | 组件级:effect 回调函数更新对应的是 组件 UI 更新 | 使用 effect 订阅,自变量变化后,Vue3执行“订阅其变化的 effect 回调函数” watchEffect首次执行/依赖的自变量变化,执行更新 AOT:通过 PatchFlags 标记 VNode 是否为可变的 |
1、调用组件的 render ,生成对应 VNode 2、与上一次更新的 VNode 同时传入 patch ,找到变化,最终执行对应的 DOM 操作 |
React | 全量引入运行时代码,重运行时框架 极致的运行时框架 应用级:每次更新都是从应用的根结点开始,遍历整个应用 |
(内部有优化机制) |
6、为什么React16要使用fiber重构?有什么优点?
解答:重构的原因主要是旧架构无法实现 Time Slice
那为什么要实现 时间切片?是因为前端当前有两大瓶颈:
- CPU瓶颈(根本原因是,渲染流水线和js执行同时作为宏任务,如果js执行时间过长,渲染流水线图片绘制低于60帧-屏幕刷新率,就会掉帧、卡顿)
- I/O 瓶颈(虽然下载速度无法控制,但是 React 希望通过划分优先级,和统一调度来优化,该方案的核心需要可中断更新,即时间切片)
React 在运行时将 VDOM 的执行过程拆分成一个一个独立宏任务,每个宏任务执行时间限制在一定范围内。
- CPU瓶颈 - 通过将一个长宏任务,拆解成多个短宏任务,不影响渲染流水线
- I/O瓶颈 - 实现可中断更新,在一个短宏任务完成前,下一个短宏任务开始前,检查是否应该中断
7、fiber 是怎么实现的?
在 render 阶段,任务是可以随时中止的,根据当前的可用时间处理一个或多个 fiber 节点,得益于 fiber 对象中存储的元素上下文信息以及构成的链表结构,使其能够将执行到一半的工作仍保存在内存的链表中。在重新获得控制权后,又可以根据保存在内存中的上下文信息快速找到停止的fiber节点,然后继续工作执行工作单元。
render 阶段产生的结果是一个 标记了 flags/effect-list 的节点树 wip(workInProgress)。