第2章 React核心基础高频面试题:JSX原理、虚拟DOM、生命周期、事件机制

本章定位:跨端开发面试中,React核心基础是必考模块。掌握JSX编译原理、虚拟DOM diff策略、生命周期与Hooks映射、合成事件机制,是回答80%基础题的底层能力。

一、核心知识结构速览

面试主题 核心考点 跨端侧重点
JSX原理 编译为React.createElement、babel插件、React.Children RN中JSX同样编译为原生视图树
虚拟DOM diff算法(同层/key/Fiber)、调和过程 跨端需了解React Native的Shadow Tree
生命周期 Class组件三阶段(挂载/更新/卸载)、Hooks替代方案 RN中onLayout对应didMount;useEffect清理
事件机制 合成事件、事件委托、原生事件混用 RN中触摸事件需用PanResponder/Gesture Handler

二、知识结构图:JSX编译与虚拟DOM流程

JSX 模板 Babel @babel/preset-react React.createElement() 虚拟DOM {type, props, children} Diff 调和 同层比较 + key Fiber 架构 可中断 / 优先级 commit 阶段 DOM 更新 / useEffect 合成事件系统 事件委托到document React Native 映射 加分点:JSX 中 {} 表达式、React.Children 加分点:RN 触摸事件需额外处理

三、面试问答卡片

❓ 面试问题:JSX 是如何被浏览器识别的?React 为什么选择 JSX?
考察点编译原理、React.createElement 签名、babel 作用、跨端差异性
回答框架① JSX 是语法糖→② Babel 编译为 React.createElement(type, props, ...children)→③ createElement 返回虚拟DOM对象→④ 优势:声明式、可组合、类型安全。跨端中 JSX 编译为原生视图树。
示例回答JSX 不是合法 JS,需 Babel 转译。例如 <div className="box">Hi</div> 编译为 React.createElement('div', { className:'box' }, 'Hi')。它让 UI 结构更直观,跨端时 RN 用同样 JSX 生成原生组件。
可能追问JSX 中 “{}” 表达式如何编译?为什么组件首字母必须大写?React.Children 有什么用?
避坑提醒不要答“JSX 是模板引擎”,避免说“必须用 JSX”其实是可选的(createElement 直接写)。跨端面试需强调 RN 中 JSX 编译为原生视图而非 DOM。
❓ 面试问题:虚拟 DOM 比真实 DOM 快吗?diff 算法如何工作?
考察点虚拟DOM设计目的、diff策略(同层/key/Fiber)、性能本质、跨端渲染
回答框架① 不一定更快,核心是“最小化DOM操作”→② diff 规则:同层比较、key 复用、type 不同直接替换→③ Fiber 实现可中断调和→④ 跨端 RN 对应 Shadow Tree 批量更新。
示例回答虚拟DOM通过批量diff减少重排重绘。diff采用广度优先同层比较,当type变化直接替换整子树;key帮助列表复用。React Fiber将任务切片,高优先级先执行。RN中虚拟DOM对应Shadow Tree,由Yoga布局引擎计算。
可能追问为什么不直接用索引当 key?Fiber 双缓冲如何工作?React 17/18 diff 有变化吗?
避坑提醒不要说“虚拟DOM更快”——对极简页面反而慢。避免忘记提 Fiber 的引入改变了 diff 的中断机制。跨端需补充 Yoga 布局到原生视图的映射。
❓ 面试问题:React 16+ 生命周期有哪些变化?Hooks 下如何替代 class 组件生命周期?
考察点废弃的API(componentWillMount等)、useEffect模拟、合成事件原理
回答框架① 挂载:constructor→render→componentDidMount(Hooks:useEffect([]))→② 更新:shouldComponentUpdate→render→componentDidUpdate(Hooks:useEffect(()=>{},[deps]))→③ 卸载:componentWillUnmount(Hooks:useEffect return 清理)→④ 合成事件:委托到根节点,提供跨平台兼容。
示例回答React 16 废弃了 componentWillMount 等生命周期,改用 getDerivedStateFromProps 和 getSnapshotBeforeUpdate。Hooks 中 useEffect 第二个参数控制执行时机;返回清理函数代替 componentWillUnmount。合成事件统一对事件进行池化,RN 中由触摸事件系统处理。
可能追问useEffect 与 useLayoutEffect 的区别?合成事件为什么要在 React 17 中绑定到 root 而非 document?RN 中如何阻止手势冒泡?
避坑提醒不要混淆 useEffect 和 class 生命周期的对应(useEffect 是异步的,useLayoutEffect 同步)。避免说“合成事件完全替代原生事件”——有时需要 e.nativeEvent。跨端面试需强调 RN 中没有 DOM 事件对象,而是原生触摸事件。
💡 本章高频追问总结:
• JSX -> 为何不能用 class 属性?(className 因 class 是保留字)
• 虚拟 DOM -> 手写一个简单的 diff 算法伪代码?
• 生命周期 -> useEffect 第二个参数为 [] 和 [a,b] 时分别如何执行?
• 事件机制 -> e.stopPropagation() 在合成事件中能阻止原生事件吗?(不能,需调用 e.nativeEvent.stopImmediatePropagation)
🏆 章节能力模型:掌握本章4个核心模块,不仅能应对字节、腾讯、阿里等大厂基础面试,也为后续跨端章节(React Native / Taro / Flutter)打下底层认知。建议结合手写代码练习:实现一个简版 JSX 编译输出、模拟虚拟DOM diff 逻辑。