关于react.js:画流程图学React17源码

34次阅读

共计 3745 个字符,预计需要花费 10 分钟才能阅读完成。

浏览前须知

流程图的内容 90% 来自于 React 技术揭秘 一书,对其内容进行整顿,不便正在学习源码的同学们可能系统性把每个要害知识点给串联起来,上面 JPG 图片比拟含糊,图片宽高比较大,用手机关上 pdf,观看起来也不不便,倡议用电脑跳转上面各个 pdf 地址进行查看,带着问题来浏览。

React 理念

1、react15 与 react > 16 架构区别性?\
2、Fiber 节点的组成?\
3、Fiber 树的构造?何为深度优先遍历?\
4、Fiber 工作原理(双缓存技术)?\
5、Fiber Mount 与 Update 流程是怎么样?\
6、JSX 与 Fiber 的区别?

pdf 地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…

React render 阶段

1、进入 render 阶段前须要干什么(判断是否异步可中断更新)?\
2、Fiber 节点的创立和 Fiber 树的构建如何开始(performUnitOfWork)?\
3、“递”阶段 beginWork 如何工作?\
4、‘归阶段’completeWork 如何工作?\
5、如何判断是 mount 还是 update?\
6、render 阶段最终的产物是什么(effectList 的生成、fiber 节点的创立)?

pdf 地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…

React commit 阶段

1、commit 阶段如何开启(commitRoot 办法)?\
2、before mutation 阶段之前做了什么(flushPassiveEffects(), 触发 useEffect 回调与其余同步工作)?\
3、rootFiber 的 effectTag 不在 effectList 怎么办?\
4、before mutation 阶段(执行 Dom 操作之前)做了什么?\
5、mutation 阶段(执行 Dom 操作)做了什么?\
6、layout 阶段(执行 Dom 操作后)做了什么?\
7、layout 之后做了什么?\
8、最终产物是什么?

pdf 地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…

React Diff 算法

1、什么是 diff 算法?\
2、diff 概念?\
3、diff 算法产生的阶段?\
4、diff 的预设限度?\
5、diff 如何实现?

pdf 地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…

React 状态更新

1、触发状态更新要害链路?\
2、触发状态更新有哪些办法?\
3、HostRoot、ClassComponent 的 Update 对象构造?\
4、ClassComponent、HostRoot 的 UpdateQueue 构造?\
5、updateQueue 的工作流程?\
6、调度优先级的过程?\
7、为什么 componentWillXXX 会触发屡次,要加个 unsafe_?\
8、如何保障 Update 不失落?\
9、ReactDOM.render 的流程?\
10、this.setState、this.forceUpdate 的流程?\
11、React 入口有哪三种模式?

pdf 地址: bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…

React Hook

1、一个极简的 useState Hook 的实现(强烈推荐,上面把这部分的代码贴出来了 ,对了解 hook 有帮忙)\
2、Hook 的数据结构(相似 updateQueue)\
3、mount/update 的调起办法会以不同dispatcher 辨别 \
4、useState 与 useReducer 原理概览(比照下面极简 useState hook 的实现)\
5、usEffect(通过前几个流程图所讲 flushPassiveEffects 办法进行切入了解)概览 \
6、useRef 原理概览?ref 的工作流程,render 阶段做了什么?commit 阶段做了什么?\
7、useMemo、useCallback 原理概览,以及 mount、update 时两者的区别

pdf 地址 \
bin-blog.oss-cn-shenzhen.aliyuncs.com/react/react…

极简 useState Hook 的实现


// 首次 render 时是 mount
let isMount = true;

// 通过 workInProgressHook 变量指向以后正在工作的 hook
let workInProgressHook;

// App 组件对应的 fiber 对象
const fiber = {
    // 保留该 FunctionComponent 对应的 Hooks 链表
    memoizedState: null,
    // 指向 App 函数
    stateNode: App
};

// APP 组件
function App() {const [num, updateNum] = useState(0);
  
    console.log(`${isMount ? 'mount' : 'update'} num: `, num);
  
    return {click() {updateNum(num => num + 1);
      }
    }
}

// 模仿 React 开始调度更新
function schedule() {
    // 更新前将 workInProgressHook 重置为 fiber 保留的第一个 Hook
    // 通过 workInProgressHook 变量指向以后正在工作的 hook
    workInProgressHook = fiber.memoizedState;
    // 触发组件 render
    fiber.stateNode();
    // 组件首次 render 为 mount,当前再触发的更新为 update
    isMount = false;
}

// 更新时底层驱动函数
function dispatchAction(queue, action) {
    // 创立 update
    const update = {
      action, // 更新执行的函数 
      next: null // 与同一个 Hook 的其余更新造成链表
    }
  
    // 环状单向链表操作
    // 产生的 update 保留在 useState 对应的 hook.queue
    if (queue.pending === null) {update.next = update;} else {
      update.next = queue.pending.next;
      queue.pending.next = update;
    }
    queue.pending = update;
  
    // 模仿 React 开始调度更新
    schedule();}


function useState(initialState) {
    let hook;
  
    if (isMount) {
      // mount 时须要生成 hook 对象
      // 保留 update 的 queue,即上文介绍的 queue
      hook = {
        queue: {pending: null},
        // 保留 hook 对应的 state
        memoizedState: initialState,
        // 与下一个 Hook 连贯造成单向无环链表
        next: null
      }
      // 将 hook 插入 fiber.memoizedState 链表开端
      if (!fiber.memoizedState) {fiber.memoizedState = hook;} else {workInProgressHook.next = hook;}
       // 挪动 workInProgressHook 指针
      workInProgressHook = hook;
    } else {
      // update 时从 workInProgressHook 中取出该 useState 对应的 hook
      hook = workInProgressHook;
      // 在组件 render 时,每当遇到下一个 useState,咱们挪动 workInProgressHook 的指针。// 这样,只有每次组件 render 时 useState 的调用程序及数量保持一致,那么始终能够通过 workInProgressHook 找到以后 useState 对应的 hook 对象。workInProgressHook = workInProgressHook.next;
    }
  
    let baseState = hook.memoizedState;
    if (hook.queue.pending) {
      // 获取 update 环状单向链表中第一个 update
      let firstUpdate = hook.queue.pending.next;
  
      do {
        // 执行 update action
        const action = firstUpdate.action;
        baseState = action(baseState);
        firstUpdate = firstUpdate.next;
        // 最初一个 update 执行完后跳出循环
      } while (firstUpdate !== hook.queue.pending.next)
      // 清空 queue.pending
      hook.queue.pending = null;
    }
    // 将 update action 执行完后的 state 作为 memoizedState
    hook.memoizedState = baseState;
  
    return [baseState, dispatchAction.bind(null, hook.queue)];
  }

正文完
 0