# Task-04-01 **Repository Path**: fishlyn/task-04-01 ## Basic Information - **Project Name**: Task-04-01 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-03-23 - **Last Updated**: 2021-03-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Part4 模块一 作业 1. 请简述 React 16 版本中初始渲染的流程 * Jsx 转换成 react 对象 * babel-react 调用 React.createElement 将 jsx 转换成描述 react 元素的对象 * Render 阶段 * 为每一个 react 构建 Fiber 对象(workInProgress Fiber 树) * 创建 Fiber 对象对应的 DOM 对象 * 为 Fiber 对象添加 effectTag 属性(记录当前 Fiber 要执行的 DOM 操作) * render 结束后,Fiber 保存在 fiberroot 中 * Commit 阶段 * 获取 Render 的结果,在 fiberroot 中新构建的 workInProgress Fiber 树 * 根据 Fiber 中的 effectTag 属性进行对应的 DOM 操作 2. 为什么 React 16 版本中 render 阶段放弃了使用递归 * 因为递归耗内存,使用的是 Javascript 自身的执行栈,一旦开始不能停止,,如果 virtualDOM 的层级很深,virtualDOM 的比对就会长期占用 Javascript 主线程,递归更新的时间会超过 16ms,会让用户感知到页面的卡顿 * 采用循环模拟递归,比对的过程是利用浏览器的空闲时间完成的,不会长期占用主线程,可以很好的解决页面卡顿的问题 3. 请简述 React 16 版本中 commit 阶段的三个子阶段分别做了什么事情 * **before mutation** 阶段:处理类组件的 getSnapShotBeforeUpdate 生命周期函数 * 处理 DOM 节点渲染 / 删除后的 autoFocus、blur逻辑 * 调用 getSnapshotBeforeUpdate 生命周期钩子 * 调度 useEffect * **mutation** 阶段:将 workInProgress Fiber 树变成 current Fiber 树 * 如果该 Fiber 类型是 ClassComponent 的话,执行 getSnapshotBeforeUpdate 生命周期 API,将返回的值赋到 Fiber 对象的__reactInternalSnapshotBeforeUpdate 上 * 如果该 Fiber 类型是 FunctionComponent 的话,执行 hooks 上的 effect 相关 API * **layout** 阶段(执行 DOM 操作后):commitHookEffectList() 阶段,调用类组件生命周期函数或者函数组件的钩子函数 * 重置 nextEffect,useEffect 是让 FunctionComponent 产生副作用的 hooks,当使用 useEffect 后,会在 Fiber 上的 updateQueue.lastEffect 生成 effect 链 * 循环 FunctionComponent 上的 effect 链,并根据每个 effect上 的 effectTag,执行 destroy / create 操作 4. 请简述 workInProgress Fiber 树存在的意义是什么 * 为了实现双缓存 * React 中会同时存在两颗 Fiber 树,当前显示的内容对应的 Fiber 树为 current Fiber 树,正在内存中构建的 Fiber 树为 workInProgress Fiber 树,反映了未来刷新到页面上的状态 * current Fiber 树的节点为 current fiber,workInProgress Fiber 树的节点为 workInProgress fiber,通过 alternate 属性连接 * React 应用的根节点通过 current 指针,在不同的 Fiber 树的 rootFiber 间切换来实现 Fiber 树的切换 * 当 workInProgress Fiber 树构建完成交给 Renderer 渲染在页面上后,应用根节点的 current 指针指向 workInProgress Fiber 树,此时 workInProgress Fiber 树就变为 current Fiber 树。每次状态更新都会产生新的 workInProgress Fiber 树,通过 current 与 workInProgress 的替换,完成 DOM 更新 * 由于有两颗 Fiber 树,实现了异步中断时,更新状态的保存,中断回来以后可以拿到之前的状态,并且两者状态可以复用,节约了从头构建的时间