更新后为单节点
* 更新前为单节点
A1 -> A2
A1 -> B1
* 更新前为多节点
A1B1 -> A1
只有在 key 与 type 相同时 才能复用当前节点 其他情况都不能复用
实现思路:
-
找出比较节点的
key与type相同则复用 -
删除其他不能复用的兄弟节点
代码实现
// 单节点
function reconcilerSingleElement(
returnFiber: FiberNode,
currentFiber: FiberNode | null,
element: ReactElementType
) {
// 1. 查看是否可以复用fiber currentFiber 与 wip 的fiber 做对比
const key = element.key;
while (currentFiber !== null) {
// update
if (currentFiber.key === key) {
// key 相同
if (element.$$typeof === REACT_ELEMENT_TYPE) {
if (currentFiber.type === element.type) {
// 当前节点的key 与 type 相同
// 复用 fiber
const existing = useFiber(currentFiber, element.props);
existing.return = returnFiber;
// 当前节点可复用 删除剩下的兄弟节点
deleteRemainingChildren(returnFiber, currentFiber.sibling);
return existing;
}
// type 不同 说明没有可复用的节点 删除所有旧的节点
deleteRemainingChildren(returnFiber, currentFiber);
break;
} else {
if (__DEV__) {
console.warn('还未实现的reconciler', element);
break;
}
}
} else {
// key 不同删除当前的节点 并继续遍历
deleteChild(returnFiber, currentFiber);
currentFiber = currentFiber.sibling;
}
}
// 创建fiber
const fiber = createFiberFormElemnt(element);
fiber.return = returnFiber;
return fiber;
}