列表的key主要是为了react渲染阶段更好的协调(reconciliation),diff时更好的识别react元素,减少dom的创建和操作,提升效率。
设定key值方式:
key需满足条件:
以useState举例来说,state和修改state的操作队列一起存在Fiber节点的hooks数组中,形式类似。
fiber.hooks = [
{
state: '', // 第0个hook的当前状态值
queue: [], // 第0个hook待执行的操作队列
},
{
state: '', // 第1个hook的当前状态值
queue: [], // 第1个hook待执行的操作队列
},
{
memorizedState: [...,...]
}
...
];
渲染时,函数组件作为函数执行时,函数内每执行一个hook函数,就按顺序从fiber.hooks取出hook的对应状态和操作队列。如果hook函数不是在函数组件顶层,可能会打乱获取hook对应状态和操作队列的顺序。
一、基本过程
二、beginWork(current | null, workInProgress, renderLanes)
最终,都会进入reconcileChildren方法
最后会执行moutChildFibers或reconcileChildFibers,workInProgress.child = moutChildFibers(...)或reconcileChildFibers(...),其中reconcileChildFibers会为生成的Fiber节点带上effectTag属性,moutChildFibers则不会。
fiber.stateNode会在completeWork中创建,mount时只有rootFiber会赋值Placement effectTag,在commit阶段直接一次插入操作。
三、completeWork(current | null, workInProgress, renderLanes)
类似beginWork,completeWork也是针对不同fiber.tag调用不同的处理逻辑
fiber.tag为HostComponent时,最主要的逻辑是调用updateHostComponent,在updateHostComponent内部,被处理完的props会赋值给workInProgress.updateQueue,并最终会在commit阶段渲染到页面上。
mount时,只会在rootFiber存在Placement effectTag,那么commit阶段是如何通过一次插入DOM操作的?原因是completeWorkd中appendAllChildren方法,由completeWork属于‘归’阶段调用函数,每次调用appendAllChildren时都会将已生成的子孙DOM节点插入当前生成的DOM节点下,‘归’到rootFiber时,已经构建好了离屏DOM树。
在completeWork的上层函数completeUnitOfWork中,每执行完completeWork且存在effectTag的Fiber节点会被保存在一条被称为effectList的单向链表中。
在‘归’阶段,所有有effectTag的Fiber节点都会被追加在effectList中,最终形成一条以rootFiber.firstEffect为起点的单向链表。rootFiber.firstEffect.nextEffect.nextEffect....
结尾:render全部工作完成,在performSyncWorkOnRoot函数中,fiberRootNode被传递给commitRoot方法,开启commit阶段工作流程。
commitRoot(root) commit阶段的起点。
一、commit阶段主要工作
before mutation阶段之前 和 layout阶段之后,还有一些额外工作:useEffect的触发、优先级相关的重置、ref的绑定/解绑
before mutation阶段之前:主要做一些变量赋值,状态重置的工作
layout阶段之后:
各阶段的工作
整个过程就是遍历effectList并调用commitBeforeMutationEffects函数处理,
mutation阶段也是遍历effectList,执行函数。这里执行的是commitMutationEffects
与前两个阶段类似,layout阶段也是遍历effectList,执行函数。 具体执行的函数是commitLayoutEffects
结束:root.current = finishedWork;
reconcileChildFibers
参见文-章:
Build your own React (pomb.us)
React技术揭秘 (iamkasong.com)
注:以上,如有不合理之处,还请帮忙指出,大家一起交流学习~