react面试题-----React 核心原理与生态高频面试题
·
React 核心原理与生态高频面试题
1. React Fiber 架构原理
Q: 请详细解释React Fiber架构的设计动机、核心原理和它对React性能的改进
A:
设计动机:
- 解决同步渲染导致的页面卡顿问题
- 实现增量渲染和任务分片
- 支持更高优先级的更新(如动画)
核心原理:
- Fiber节点:虚拟DOM的扩展数据结构,包含组件信息、props、state等
class FiberNode { tag: WorkTag, // 组件类型 stateNode: any, // 对应实例 return: FiberNode, // 父节点 child: FiberNode, // 第一个子节点 sibling: FiberNode, // 兄弟节点 alternate: FiberNode, // 当前/workInProgress树 effectTag: SideEffectTag, // 副作用标记 nextEffect: FiberNode // 下一个有副作用的节点 } - 双缓冲机制:current树(当前UI)和workInProgress树(构建中)
- 调度机制:requestIdleCallback模拟实现时间分片
性能改进:
- 可中断渲染:将渲染任务拆分为小任务单元
- 优先级调度:区分高优先级(用户交互)和低优先级更新(数据获取)
- 更平滑的并发更新体验
2. React Hooks 实现原理
Q: React Hooks是如何在函数组件中实现状态管理的?解释useState和useEffect的内部实现机制
A:
底层实现:
-
Hooks存储:使用链表结构存储hooks状态
let currentlyRenderingFiber; let workInProgressHook; let currentHook; function mountWorkInProgressHook() { const hook = { memoizedState: null, baseState: null, queue: null, baseUpdate: null, next: null }; if (!workInProgressHook) { currentlyRenderingFiber.memoizedState = workInProgressHook = hook; } else { workInProgressHook = workInProgressHook.next = hook; } return workInProgressHook; } -
useState原理:
- 首次渲染:创建hook对象并初始化state
- 更新阶段:从队列中获取最新状态
- 触发更新:dispatchAction将更新加入队列并调度渲染
-
useEffect原理:
- 渲染后比较依赖项
- 生成effect链表
- commit阶段执行副作用
function updateEffect(create, deps) { const hook = updateWorkInProgressHook(); const nextDeps = deps === undefined ? null : deps; if (currentHook !== null) { const prevEffect = currentHook.memoizedState; if (nextDeps !== null) { const prevDeps = prevEffect.deps; if (areHookInputsEqual(nextDeps, prevDeps)) { return; } } } currentlyRenderingFiber.effectTag |= Update | Passive; hook.memoizedState = pushEffect( HookHasEffect | hookEffectTag, create, undefined, nextDeps ); }
3. 虚拟DOM与Diff算法
Q: React的虚拟DOM Diff算法具体如何工作?与传统Diff算法相比有哪些优化?
A:
Diffing策略:
- 层级比较:只比较同层级节点,复杂度O(n)
- 类型比较:
- 元素类型不同:直接销毁重建
- 相同类型:更新属性
- Key优化:稳定key帮助识别节点移动
优化算法:
function reconcileChildrenArray(
returnFiber: Fiber,
currentFirstChild: Fiber | null,
newChildren: Array<*>,
lanes: Lanes
): Fiber | null {
// 1. 遍历新旧子节点
// 2. 通过key匹配可复用节点
// 3. 处理节点移动/插入/删除
// 4. 返回新的第一个子节点
}
性能优化:
- 批处理更新:合并多次setState
- 跳过子树:shouldComponentUpdate/PureComponent
- Fiber中断:高优先级任务可打断Diff过程
4. React 18并发特性
Q: React 18引入了哪些并发特性?解释startTransition和useTransition的工作原理
A:
并发特性:
- 自动批处理:合并更多场景的状态更新
- Transition:区分紧急和非紧急更新
- Suspense SSR:流式服务器渲染
startTransition:
function App() {
const [isPending, startTransition] = useTransition();
const [tab, setTab] = useState('home');
function selectTab(nextTab) {
startTransition(() => {
setTab(nextTab); // 非紧急更新
});
}
return (
<>
{isPending && <Spinner />}
<TabButton onClick={() => selectTab('about')} />
</>
);
}
工作原理:
- 标记非紧急更新
- 可被高优先级更新打断
- 使用lane模型管理更新优先级
5. React生态系统设计
Q: 如何设计一个可扩展的React组件库?需要考虑哪些架构原则和工程化实践?
A:
架构原则:
-
原子设计:
- Atoms(按钮/输入框)
- Molecules(搜索框=输入框+按钮)
- Organisms(完整功能区块)
-
分层设计:
- 基础层:无状态UI组件 - 功能层:带业务逻辑的复合组件 - 容器层:数据获取/状态管理
工程化实践:
-
模块打包:
// rollup.config.js export default { input: 'src/index.js', output: [ { file: 'dist/esm.js', format: 'es' }, { file: 'dist/cjs.js', format: 'cjs' } ], external: ['react', 'react-dom'] }; -
文档驱动:集成Storybook/Docz
-
样式方案:
- CSS-in-JS (styled-components)
- CSS Modules
- Utility-First (Tailwind)
-
测试策略:
// 组件测试示例 test('Button renders correctly', () => { render(<Button>Click</Button>); expect(screen.getByText('Click')).toBeInTheDocument(); });
6. 状态管理库对比
Q: 对比Redux、MobX和Recoil的核心实现原理和适用场景
A:
实现原理对比:
| Redux | MobX | Recoil | |
|---|---|---|---|
| 编程范式 | 函数式/不可变 | 响应式/OOP | 原子状态 |
| 数据流 | 单向 | 自动追踪 | 订阅/发布 |
| 核心机制 | 纯函数Reducer | Observable/Reaction | Atom/Selector |
| 调试工具 | 时间旅行 | 动作日志 | 开发中 |
适用场景:
- Redux:大型应用、需要严格状态轨迹
- MobX:中小型应用、快速开发
- Recoil:需要细粒度更新、实验性功能
7. 性能优化体系
Q: 构建完整的React应用性能优化体系应该包含哪些方面?
A:
优化体系:
-
加载时优化:
- 代码分割 (React.lazy + Suspense)
- 资源预加载 (preload/prefetch)
- 服务端渲染/静态生成
-
运行时优化:
// 避免重复渲染 const MemoComp = React.memo(Comp, (prev, next) => { return prev.id === next.id; }); // 避免重复计算 const data = useMemo(() => transform(rawData), [rawData]); -
渲染优化:
- 虚拟列表 (react-window)
- 按需渲染 (Intersection Observer)
- 避免布局抖动
-
监控体系:
// 使用web-vitals库 import {getCLS, getFID, getLCP} from 'web-vitals'; getCLS(console.log); getFID(console.log); getLCP(console.log); -
构建优化:
- Tree Shaking (ES模块)
- 代码压缩 (Terser)
- 持久缓存 (contenthash)
更多推荐
所有评论(0)