175-2108-6175
网站建设资讯详细

Hook是如何存储的?Hook存储原理是什么?

日期:2022-09-06  作者:千语创想  浏览:4572

状态总要持久化存储才行,不然前端就混不下去了,只能去炒粉了。我们都知道React 处理 class 组件的方式是将 class 实例化,所以 class 组件将方法、状态、钩子作为成员属性直接使用就可以了。

而 React 在处理函数组件时是将其当作函数调用的,没有实例可言,自然也不能将「状态」或是「副作用」挂在原型上。所以只能将 Hook 放在一个和函数组件有关联的地方,即函数组件在渲染过程中对应的 Fiber Node。函数组件在渲染时将 Hook 按照调用顺序以链表的形式挂在 Fiber Node 上面。得到的链表如下所示,其中 Fiber Node 的属性 memoizedState 用来指向Hook 链表的第一个节点,Hook 的属性 memoizedState 用来存放 state 值或 effect回调函数。

挂载 Hook 的伪代码如下所示:

function renderWithHooks(current) {
  //current为当前正在处理的Fiber Node  //nextCurrentHook先指向第一个Hook  nextCurrentHook = current !== null ? current.memoizedState : null
  //。。。省略其他代码
  //执行函数组件  let children = Component(props, refOrContext);

  //将指向链表第一个节点的firstWorkInProgressHook  //赋值给currentlyRenderingFiber.memoizedState  const renderedWork: Fiber = (currentlyRenderingFiber: any);

  //将Hook挂在FiberNode.memoizedState下  renderedWork.memoizedState = firstWorkInProgressHook; 
  renderedWork.expirationTime = remainingExpirationTime;

  //将Effect Hook挂在FiberNode.updateQueue下  renderedWork.updateQueue = (componentUpdateQueue: any);
  renderedWork.effectTag |= sideEffectTag;

  //重置Hook指针的指向,使每一个FiberNode都有一个专属于自身的、独立的链表  currentHook = null;
  nextCurrentHook = null;
  firstWorkInProgressHook = null;
  workInProgressHook = null;
  nextWorkInProgressHook = null;}function mountWorkInProgressHook() {
  const hook = {
    memoizedState: null,
    baseState: null,
    queue: null,
    baseUpdate: null,
    next: null,
  };
  if (workInProgressHook === null) {
    //如果当前Hook 链表为空则证明是第一次调用Hook    //需将当前调用Hook作为链表中的第一个节点    firstWorkInProgressHook = workInProgressHook = hook;
  } else {
    // 其余Hook均按顺序挂在上一个Hook的next下,形成一个链表结构    workInProgressHook = workInProgressHook.next = hook;
  }
  return workInProgressHook;}function updateWorkInProgressHook() {
  //在每次渲染时,nextCurrentHook最开始都会指向第一个Hook  currentHook = nextCurrentHook;
  const newHook = {
    memoizedState: currentHook.memoizedState,
        baseState: currentHook.baseState,
    queue: currentHook.queue,
    baseUpdate: currentHook.baseUpdate,
    next: null,
  };

  //将Hook从原链表中取出,放进新的链表中  if (workInProgressHook === null) {
    workInProgressHook = firstWorkInProgressHook = newHook;
  } else {
    workInProgressHook = workInProgressHook.next = newHook;
  }
  //指向下一个Hook  nextCurrentHook = currentHook.next;
  return workInProgressHook;}

React Hooks 的存取原理

每个组件的 fiber 上都有个 memorizedState 属性用于存储这个组件的所有 hooks。hooks 中的每个 hook 也有个 memorizedState 用于存储这个 hook 的数据。而每个 hook 还有个 next 指向下一个 hook。
这里我们用链表实现 hooks 的存储,也可以用数组实现,只要有顺序就行。


转载请注明来自:https://www.qianyuthink.com/news/7262.html