← 返回目录

第 26 卷

第 26 / 28 卷日期:

5// 紧急更新:更新输入框内容(优先执行,不被中断)

6setInputValue(e.target.value);

7

8//非紧急更新:筛选列表(可被输入操作中断)
9startTransition(() => {
10setFilteredList(filterData(e.target.value));
11});
12}

(4) suspense 与流式服务端渲染(Streaming SSR)

增强了 suspense 的能力,使其支持服务端渲染场景:

• 流式 SSR:服务端可分块发送 HTML 内容,先发送静态部分,再发送动态数据加载完成的部分,减

少页面“白屏时间”;

• suspense fallback:在服务端渲染时,若组件数据未加载完成,可先渲染 fallback 占位符(如加

载中),数据加载完成后替换为真实内容。

3. 开发体验与稳定性优化

(1)严格模式(StrictMode)增强

新增“组件自动卸载与重新挂载”检测,用于发现因未清理副作用(如定时器、事件监听)导致的内存泄漏问题。在严格模式下,React 会模拟组件的挂载-卸载-重新挂载过程,若存在未清理的副作用,

会触发警告。

(2)废弃与兼容处理

废弃了部分旧 API(如 ReactDOM.unmountComponentAtNode,替代为 root.unmount()),同时提供兼容层,确保旧版代码可正常运行;优化了错误边界(Error Boundary)的能力,使其能捕获更

多场景的错误(如并发渲染中的错误)。

4. 其他重要特性

• useId:生成跨服务端和客户端的唯一 ID,解决服务端渲染时 ID 不匹配的问题(如表单标签关联、

组件唯一标识);

  • useTransition:Hook 版本的 startTransition,用于在函数组件中标记过渡更新;

• useDeferredValue:延迟更新非紧急状态,类似 useTransition,但更侧重“值的延迟传递”(如

延迟传递筛选后的列表数据)。

三十八、在 React 17 中,事件处理机制经历了哪些变化?特别是与之前版

本相比,事件委托的处理有何不同?

React 17 对事件处理机制的修改核心是「调整事件委托的目标节点」,同时保持合成事件的 API 完全兼容(开发者无需修改代码)。此外,还优化了事件系统的兼容性和可维护性,解决了旧版本事件委

托的部分痛点。

1. 核心变化一:事件委托目标从 document 改为根节点(root)

这是 React 17 事件机制最核心的变化,直接影响事件冒泡和委托的底层逻辑:

(1)React 16 及之前的事件委托逻辑

  • 所有 React 合成事件(如 onClick、onChange)都委托到 document 节点上;

• 当用户触发真实 DOM 事件时,事件冒泡到 document 节点,被 React 统一的事件监听器捕获,再

分发到对应的组件。

痛点:

• 1. 若第三方库或原生代码修改了 document 的事件监听器(如阻止冒泡),会干扰 React 事件的

正常触发;

  • 2. 服务端渲染(SSR)时,document 可能不存在,需额外处理事件绑定逻辑;

• 3. 多个 React 应用共存时(如同一页面嵌入多个独立 React 应用),所有应用的事件都会委托到

document,可能出现冲突。

(2)React 17 的事件委托逻辑

• 将事件委托的目标从 document 改为「应用的根节点」(即 ReactDOM.render 挂载的节点,如

<div id="root">);

• 每个 React 应用的事件监听器都绑定在自己的根节点上,事件冒泡到根节点后被 React 捕获并分

发。

优势:

  • 1. 避免与第三方库/原生代码的事件冲突,提升事件系统的稳定性;
  • 2. 简化服务端渲染的事件处理逻辑;
  • 3. 支持同一页面多个 React 应用独立运行,互不干扰。

2. 核心变化二:原生事件与合成事件的冒泡关系调整

React 17 之前,合成事件的冒泡是在 document 节点完成的,因此原生事件若在 document 之前阻止冒泡,会导致合成事件无法触发;React 17 中,合成事件的冒泡在根节点完成,原生事件与合成事

• 若在原生事件中阻止冒泡(e.stopPropagation()),且该事件的冒泡范围未到达根节点,则不会影

  • 若原生事件冒泡到根节点后被阻止,则合成事件的冒泡会被中断(但合成事件本身仍会触发)。

示例:

Code block

1 2// 原生事件绑定在根节点的子节点上

3document.getElementById('child').addEventListener('click', (e) => {
4e.stopPropagation(); //阻止冒泡到根节点
5});

6 7// React 组件的合成事件

8function App() {

9const handleClick = () => console.log('合成事件触发');
10return <div id="child" onClick={handleClick}>点击</div>;
11}

React 17 中,点击后合成事件仍会触发(因为事件委托在根节点,原生事件阻止冒泡未到达根节点);React 16 及之前,合成事件不会触发(因为原生事件阻止冒泡后,事件无法到达 document 节

点)。

3. 其他变化:事件系统的底层重构与兼容性优化

•(1)废弃了旧版的事件池(SyntheticEvent Pool):React 17 之前,合成事件对象会被复用,需

调用 e.persist() 才能在异步回调中访问;React 17 中,合成事件对象不再复用,可直接在异步回调中访问,无需调用 e.persist();

•(2)优化了对浏览器原生事件的兼容性处理:支持更多边缘浏览器的事件类型,提升事件系统的

鲁棒性;

•(3)简化了事件绑定的底层代码:React 17 重写了事件绑定的核心逻辑,减少了冗余代码,提升

了事件系统的可维护性。

4. 关键总结:API 兼容,底层优化

React 17 的事件机制变化均为底层实现调整,未修改任何合成事件的 API(如 onClick、e.target、 e.preventDefault 等),因此开发者无需修改现有代码即可升级。核心价值在于提升事件系统的稳定

性、兼容性和可扩展性,解决了旧版本事件委托的多个痛点。

三十九、React 18 引入了自动批处理。请解释什么是批处理,以及自动批

处理如何改善了 React 应用的性能?

全站分卷索引 · 28 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷
  11. 11第 11 卷
  12. 12第 12 卷
  13. 13第 13 卷
  14. 14第 14 卷
  15. 15第 15 卷
  16. 16第 16 卷
  17. 17第 17 卷
  18. 18第 18 卷
  19. 19第 19 卷
  20. 20第 20 卷
  21. 21第 21 卷
  22. 22第 22 卷
  23. 23第 23 卷
  24. 24第 24 卷
  25. 25第 25 卷
  26. 26第 26 卷
  27. 27第 27 卷
  28. 28第 28 卷