当前位置:

「06」接入状态更新机制

访客 2023-08-20 1022 0

在前面已经实现了Update的基本架构,接下来的工作包括:

  • 实现mount时调用的API
  • 将该API接入上述Update更新机制中

目前需要考虑的事情:

「06」接入状态更新机制

  • 更新可能发生于任意组件,而更新流程是从根节点递归的
  • 需要一个统一的根节点保存通用信息
ReactDOM.createRoot(rootElement).render()

IT社区

对应到源码内部,执行ReactDOM.createRoot会生成一个fiberRootNode,然后传进来的rootElement这个DOM也有对应的节点即hostRootFiber,执行render方法,传进去App组件,就挂载到hostRootFiber

实现fiberRootNode
  • container保存对应宿主环境挂载的节点,暂时定义一个描述宿主环境对应方法的文件hostConfig.ts
编程社区

react-reconciler/src/hostConfig.ts

exporttypeContainer=any;https://www.swvq.com

react-reconciler/src/fiber.ts

IT社区

fiberRootNode的current指针指向hostRootFiberfinishiedWork指向已经更新完成的整个hostRootFiber

exportclassFiberRootNode{container:Container;current:FiberNode;finishedWork:FiberNode|null;constructor(container:Container,hostRootFiber:FiberNode){this.container=container;this.current=hostRootFiber;hostRootFiber.stateNode=this;this.finishedWork=null;}}实现mount时调用的api

**新建react-reconciler/src/fiberReconciler.ts**对外暴露两个函数分别是:createContainerupdateContainer

exportfunctioncreateContainer(container:Container){}exportfunctionupdateContainer(container:Container){}

实现createContainer这个方法可以初始化一个hostRootFiberFiberRootNode,并且调用createUpdateQueue就能够实现fiberNode与更新机制的关联

exportfunctioncreateContainer(container:Container){consthostRootFiber=newFiberNode(HostRoot,{},null);constroot=newFiberRootNode(container,hostRootFiber);hostRootFiber.updateQueue=createUpdateQueue();returnroot;}来源于

实现updateContainercreateUpdate传入element就表明更新与这个element相关,之后的更新就会对这个element进行

exportfunctionupdateContainer(element:ReactElementType|null,root:FiberRootNode){consthostRootFiber=root.current;constupdate=createUpdate(element);enqueueUpdate(hostRootFiber.updateQueueasUpdateQueue,update);scheduleUpdateOnFiber(hostRootFiber);returnelement;}

完整代码

import{Container}from'hostConfig';import{ReactElementType}from'shared/ReactTypes';import{FiberNode,FiberRootNode}from'./fiber';import{createUpdate,createUpdateQueue,enqueueUpdate,UpdateQueue}from'./updateQueue';import{scheduleUpdateOnFiber}from'./workLoop';import{HostRoot}from'./workTags';exportfunctioncreateContainer(container:Container){consthostRootFiber=newFiberNode(HostRoot,{},null);constroot=newFiberRootNode(container,hostRootFiber);hostRootFiber.updateQueue=createUpdateQueue();returnroot;}exportfunctionupdateContainer(element:ReactElementType|null,root:FiberRootNode){consthostRootFiber=root.current;constupdate=createUpdate(element);enqueueUpdate(hostRootFiber.updateQueueasUpdateQueue,update);scheduleUpdateOnFiber(hostRootFiber);returnelement;}如何让updateContainer与renderRoot更新流程串联上

workLoop中实现scheduleUpdateOnFiber,即在fiber中调度update

exportfunctionscheduleUpdateOnFiber(fiber:FiberNode){//TODO调度功能//fiberRootNodeconstroot=markUpdateFromFiberToRoot(fiber);renderRoot(root);}

从当前节点遍历到root节点

//从当前节点一直遍历到根节点functionmarkUpdateFromFiberToRoot(fiber:FiberNode){letnode=fiber;letparent=node.return;//普通的fiberNodewhile(parent!==null){node=parent;parent=node.return;}//hostRootFiber的时候if(node.tag===HostRoot){returnnode.stateNode;}returnnull;}

实现createWorkInProgress

exportconstcreateWorkInProgress=(current:FiberNode,pendingProps:Props):FiberNode=>{letwip=current.alternate;//首屏渲染wip===nullif(wip===null){//mountwip=newFiberNode(current.tag,pendingProps,current.key);wip.stateNode=current.stateNode;wip.alternate=current;current.alternate=wip;}else{//updatewip.pendingProps=pendingProps;//副作用清除掉可能是上次遗留的wip.flags=NoFlags;}wip.type=current.type;wip.updateQueue=current.updateQueue;wip.child=current.child;wip.memoizedProps=current.memoizedProps;wip.memoizedState=current.memoizedState;returnwip;};整体流程
  • createContainer创建应用的根节点fiberRootNode,并将fiberRootNodehostRootFiber连接起来
  • updateContainer创建update并将update添加入updateQueue中,将首屏渲染与触发更新的机制连接了起来
触发更新机制包含
  • createUpdate更新对应的数据结构update
  • createUpdateQueue保存update的结构updateQueue
  • equeueUpdate将update插入到updatequeue中
  • processUpdateQueue基于一个基础的状态以及pendingUpdate消费update,经过计算得到最终的状态memoizedState
fiberReconciler中

当将update插入到updatequeue中之后执行scheduleUpdateOnFiber开始调度流程

workLoop中
  • scheduleUpdateOnFiber从当前节点一直遍历到fiberRootNode,接着执行renderRoot
  • renderRoot首先根据fiberRootNode的current生成workInProgressFiber接着开始更新流程

发表评论

  • 评论列表
还没有人评论,快来抢沙发吧~