React深入浅出理解

1. JSX代码如何转化为DOM

JSX是JavaScript的语法扩展,会被Babel编译为React.createElement()函数调用,该函数返回一个称为"React Element"的JavaScript对象。Babel作为工具链,主要用于将ECMAScript 2015+代码转化为向后兼容的JavaScript语法,以支持旧版浏览器。JSX语法允许开发者使用类似HTML的标签语法,降低学习成本并提升研发效率。

​关键点​​:

  • createElement函数需要三个参数:

    type: 标识节点类型(如组件或HTML标签)。

    config: 以对象形式传入,存储组件的所有属性(键值对)。

    children: 以对象形式传入,记录组件标签间的嵌套内容。

  • ReactDOM.render参数说明:

    • element: 需要渲染的React Element。

    • container: 元素挂载的目标容器(真实DOM节点)。

    -[callback]: 可选回调函数,用于处理渲染结束后的逻辑。

    go 复制代码
      整体转化流程:JSX → `createElement`→ React Element → `ReactDOM.render`→ 真实DOM。

2. React生命周期详解

生命周期描述了组件从初始化到更新或卸载的全过程,核心是渲染工作流的"封闭"和"开放"特性:

  • ​封闭​​:每个组件仅处理内部渲染逻辑。

  • ​开放​​:基于单向数据流原则实现组件间通信,通过数据变更影响渲染结果。

    生命周期方法(如render)构成了组件的"灵魂"与"躯干"。

React 15生命周期过程
  • 父组件导致子组件重新渲染时,即使props未更改,也会触发componentReceiveProps(非props变化驱动)。

  • shouldComponentUpdate返回值决定是否执行后续生命周期及重渲染。

  • componentWillUnmount触发条件:

    • 组件在父组件中被移除。

    • 父组件render中key值与上一次不一致。

React 16生命周期过程
  • 废除componentWillMount,新增getDerivedStateFromProps

  • render方法改进:支持返回元素数组或字符串(React 16前仅支持单个元素)。

  • getDerivedStateFromProps用途:

    • 仅用于派生/更新state(非依赖组件,无法访问this)。

    • 接收propsstate参数,返回对象(无返回值需return null)。

    • 更新机制为定向属性更新(非整体覆盖)。

  • 组件初始化渲染(挂载)对比:

  • 组件更新流程对比:

    • getDerivedStateFromProps替代componentReceiveProps(不等价)。

    • 移除componentWillUpdate,新增getSnapshotBeforeUpdate

      • 执行时机在render后、真实DOM更新前。

      • 返回值作为参数传递给componentDidUpdate,用于获取更新前的真实DOM及state/props。

3. Fiber架构核心原理

Fiber是React 16对核心算法的重写,旨在解决同步渲染导致的性能问题:

  • •将同步渲染变为异步(仅在Concurrent模式下)。

  • •拆解大更新任务为小任务,支持中断、恢复和优先级调度。

  • •将生命周期划分为render(可中断)和commit(同步执行)两阶段。

​影响与变更​​:

  • 废除API:componentWillMountcomponentWillUpdatecomponentWillReceiveProps(因异步渲染可能导致多次请求或数据不一致)。

  • 动机:配合异步渲染机制,确保数据安全性和生命周期行为的可预测性。

  • 初始化阶段流程:

    • 请求当前Fiber节点的lane(优先级)。

    • 创建update对象。

    • 调节当前节点(root Fiber)。

Render阶段工作流
  • ​WorkInProgress节点创建​​:

    • createWorkInProgress生成新节点,与current节点通过alternate互指。

    • 循环调用performUnitOfWork触发beginWork创建Fiber树。

  • ​beginWork逻辑​ ​:基于Fiber节点的tag属性调用不同创建函数。

  • ​childReconciler作用​ ​:处理Fiber节点的创建、增删改(如placeXXXdeleteXXX)。

  • ​effectList设计​​:

    • 记录需处理的副作用(如DOM变更)。

    • 实现原理:Fiber节点的flags属性(旧称effectTag)标识副作用类型(如placement表示新增DOM节点)。

  • ​Fiber树创建过程​​:

Commit阶段工作流
  • before mutation:DOM未渲染前的逻辑。

  • mutation:负责DOM渲染。

  • layout:处理DOM渲染后的收尾工作。

  • 最终将Fiber树的current指针指向workInProgress树。

4. React组件数据流动

单向数据流
  • 数据流向:父组件 → 子组件(通过props传递)。

  • 实现方式:

    • 父组件通过props传递数据或函数(子组件调用函数以参数形式返回数据)。

    • 兄弟组件通信:需通过父组件中介。

发布-订阅模式(EventBus)
  • • 示例:Socket.io或Node.js的EventEmitter。

  • API设计:

    • on():注册事件监听器。

    • emit():触发事件(可携带数据)。

    • off():移除监听器。

Context全局通信
  • 作用:跨层级组件数据传递。

  • 实现:React.createContext创建Provider和Consumer。

  • 问题:过时Context代码不优雅,新版本确保数据一致性(即使shouldComponentUpdate返回false)。

5. Redux核心概念

Redux是JavaScript状态容器,提供可预测的状态管理:

  • ​组成​​:

    • store:单一数据源(只读)。

    • action:描述变化的对象(type为必填唯一标识)。

    • reducer:处理action并更新状态。

  • 原则:state变更必须由action驱动。

6. React Hooks设计

Hooks是使函数组件更强大的"钩子",本质是一个链表:

函数组件 vs 类组件
  • ​类组件​ ​:继承class、访问生命周期、维护state、使用this

  • ​函数组件​ ​:轻量、无生命周期、无this、更契合React声明式理念(数据与渲染绑定)。

​核心Hooks​​:

  • useState:返回状态变量和更新函数(mountState初始化,updateState更新)。

  • useEffect:弥补生命周期缺失(回调中返回清除函数)。

​问题与原则​​:

  • 问题:无法完全替代类组件能力,复杂性处理较弱。

  • 使用原则:

    • 仅在React函数中调用Hook。

    • 避免在循环、条件或嵌套函数中调用。

    • 确保Hooks执行顺序一致。

7. 虚拟DOM与diff算法

虚拟DOM是描述DOM结构的JS对象,优化渲染性能:

  • ​工作流​​:

    • 挂载阶段:JSX → 虚拟DOM树 → ReactDOM.render→ 真实DOM。

    • 更新阶段:变更作用于虚拟DOM → diff算法对比差异 → 差量更新真实DOM。

  • ​价值​​:

    • 提升研发体验与效率。

    • 支持跨平台渲染(Web、iOS、Android)。

    • 实现批量更新。

​diff算法原理​​:

  • 分层对比:仅同层级节点比较。

  • 类型一致:节点类型相同才继续diff。

  • key优化:重用同层级节点。

  • 树递归:基于key进行深度比较。

8. setState工作流

  • ​行为差异​​:

    • 异步:在React钩子函数和合成事件中。

    • 同步:在setTimeoutsetInterval或原生DOM事件中(因逃脱React管控)。

  • ​Transaction机制​ ​:封装方法(如initializeperform),确保更新原子性。

9. React事件系统

原生DOM事件流
  • 三阶段:事件捕获 → 目标阶段 → 事件冒泡。

  • 事件委托:合并子元素监听逻辑到父元素。

React事件流实现
  • 绑定:通过completeWork完成。

  • 特点:document上统一事件分发函数(多次调用仅触发一次)。

  • 合成事件:封装原生事件,提供跨浏览器一致性。

相关推荐
阿珊和她的猫31 分钟前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
加班是不可能的,除非双倍日工资5 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi5 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip6 小时前
vite和webpack打包结构控制
前端·javascript
excel6 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国6 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼6 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy6 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT7 小时前
promise & async await总结
前端
Jerry说前后端7 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化