Appearance
归阶段,主要执行
completeWork
逻辑
completeWork
js
function completeWork(current, wip, renderLanes) {
//..
switch (workInProgress.tag) {
// 根据wip 的类型执行逻辑
case HostComponent:
if (current !== null && workInProgress.stateNode != null) {
updateHostComponent(current, wip, type, newProps, rootContainerInstance)
} else {
// 首屏渲染逻辑
}
}
}
function updateHostComponent(current, wip, type, newProps, rootIns) {
const instance = wip.stateNode
const currentHostContext = getHostContext()
const updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext)
// 当前节点的更新队列任务
workInProgress.updateQueue = updatePayload;
if (updatePayload) {
markUpdate(workInProgress);
}
}
// 生成 updatePayload (也就是更新信息)
function prepareUpdate(domElement, type, oldProps, newProps, rootContainerInstance, hostContext) {
// ... 更新两个props
return diffProperties(domElement, type, oldProps, newProps);
}
function diffProperties(domElement, tag, lastRawProps, nextRawProps, rootContainerElement) {
// ... 根据 wip 的 type执行相应逻辑
switch (tag) {
// 主要针对三个表单组件
case 'input':
case 'select':
case 'textarea':
// ...
default:
lastProps = lastRawProps
nextProps = nextRawProps
}
//...
for (propKey in lastProps) {
// 新旧都有的属性,或者新增的属性直接跳出循环
if (nextProps.hasOwnProperty(propKey)
|| !lastProps.hasOwnProperty(propKey)
|| lastProps[propKey] == null) {
continue;
}
//...
}
for (propKey in nextProps) {
var nextProp = nextProps[propKey]; // 新属性值
var lastProp = lastProps != null ? lastProps[propKey] : undefined;
if (!nextProps.hasOwnProperty(propKey)
|| nextProp === lastProp
|| nextProp == null && lastProp == null) {
// 更新前后相等
continue;
}
if (propKey === STYLE) {
// 传入的style 对象更新
} else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
// 传入的 dangerouslySetInnerHtml 更新
} else if (propKey == CHILDREN) {
// 传入的children 更新
} else {
(updatePayload = updatePayload || []).push(propKey, nextProp);
}
}
//...
return updatePayload
}
diffProperties
返回updatePayload
,数据结构为数组[propKey, propValue]
,返回赋值给wip.updateQueue
同时,标记该wip
有更新
js
function markUpdate(workInProgress) {
workInProgress.flags |= Update;
}
最后,通过 commit
阶段进行渲染
completeUnitOfWork
更新过程中,不再参考首屏渲染的 DFS(深度优先)逐个节点进行渲染,而是在完成
completeWork
之后,将需要更新的FiberNode
组装成链表effectList
,commit
阶段只需要更新这条链表
以上操作发生在 completeUnitOfWork
js
function completeUnitOfWork(unitOfWork) {
let completedWork = unitOfWork
do {
// ...
if ((completedWork.flags & Incomplete) === NoFlags) {
let next;
// 处理Fiber节点, 会调用渲染器
// (调用react-dom包, 关联Fiber节点和dom对象, 绑定事件等)
next = completeWork(current, completedWork, subtreeRenderLanes);
// 处理单个节点
if (next !== null) {
// 如果派生出其他的子节点, 则回到`beginWork`阶段进行处理
workInProgress = next;
return;
}
// 重置子节点的优先级
resetChildLanes(completedWork);
if (returnFiber !== null
&& (returnFiber.flags & InComplete) === NoFlags) {
// 当前 unitOfWork 没有未完成递归操作的父节点
if (returnFiber.firstEffect === null) {
returnFiber.firstEffect = completedWork.firstEffect
}
if (completedWork.lastEffect !== null) {
if (returnFiber.lastEffect !== null) {
returnFiber.lastEffect.nextEffect = completedWork.firstEffect;
}
returnFiber.lastEffect = completedWork.lastEffect;
}
}
const flags = completedWork.flags;
if (flags > PerformedWork) {
//PerformedWork是提供给 React DevTools读取的, 所以略过PerformedWork
if (returnFiber.lastEffect !== null) {
returnFiber.lastEffect.nextEffect = completedWork;
} else {
returnFiber.firstEffect = completedWork;
}
returnFiber.lastEffect = completedWork;
}
}
const siblingFiber = completedWork.sibling;
if (siblingFiber !== null) {
// 如果有兄弟节点, 返回之后再次进入`beginWork`阶段
workInProgress = siblingFiber;
return;
}
// 移动指针, 指向下一个节点
completedWork = returnFiber;
workInProgress = completedWork;
} while (completedWork !== null);
}
effectList
中第一个Fiber节点
保存在其 父节点 returnFiber.firstEffect
,最后一个元素保存在returnFiber.lastEffect
- 最后,所有包含
flags
的FiberNode 都会被追加在 effectList
中,最终形成一条以rootFiber.firstEffect
为起点的链表(指向第一个具有 flag 的叶节点) - 然后通过
nextEffect
指向下一个 带有 flags 的节点