render函数的子结是数组类型的时候,有两个注意的点
1fiber是单链表结构,所以不能用双指针去优化diff ,而是用两层遍历,
第一层,只要遇到无法复用的节点就break,所以必须设置唯一的key,不到万不得已不要用数组下标做key,因为类型不同也无法复用。目的就是尽量减少后面的操作。
第二层,对比剩下的新旧节点判断是否能复用,然后插入和删除和移动。
2lastPlacedIndex
理解
abcd badc
新顺序 a在b后面 ,如果a b能够复用的话,在老顺序 同样也要保证a在b后面,新顺序后面的节点,如果能够复用,必须保证出现在老顺序最后,所以用lastPlacedIndex记录复用节点的最大索引,最靠右侧,后面的可复用节点如果小于lastPlacedIndex 需要移动。大于的话就保持原位置。
所以当把abcd 改成dabc时,移动了a b c 而不是把d移动到第一位,消耗的性能大,尽量少进行类似的操作。
// 协调子fiber的过程
import {
createFiberFromElement,
createFiberFromText,
createWorkInProgress
} from ‘./ReactFiber’;
import {
Placement,
Deletion
} from ‘shared/ReactSideEffectTags’;
import {
HostText
} from ‘shared/ReactWorkTags’;
import {REACT_ELEMENT_TYPE} from ‘shared/ReactSymbols’;
// 对于协调单一节点过程中,创建的workInProgress需要去掉他的sibling指向
function useFiber(fiber, pendingProps) {
const clone = createWorkInProgress(fiber, pendingProps);
clone.sibling = null;
clone.index = 0;
return clone;
}
export function cloneChildFibers(current, workInProgress) {
const currentChild = workInProgress.child;
if (!currentChild) return;
let newChild = createWorkInProgress(currentChild, currentChild.pendingProps);
workInProgress.child = newChild;
newChild.return = workInProgress;
while (currentChild.sibling) {
currentChild = currentChild.sibling;
newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps);
newChild.return = workInProgress;
}
newChild.sibling = null;
}
// 为了在2个方法中复用一批共用方法
// shouldTrackSideEffects标示是否标记fiber的effectTag
// 对于首次渲染,不需要标记effectTag,因为completeWork时会appendAllChildren,最后一次渲染整棵树
// 对于单次更新,需要标记更新fiber的effectTag
function ChildReconciler(shouldTrackSideEffects) {
function createChild(returnFiber, newChild, expirationTime) {
if (typeof newChild === ‘number’ || typeof newChild === ‘string’) {
const created = createFiberFromText(newChild, expirationTime);
created.return = returnFiber;
return created;
}
if (typeof newChild === ‘object’ && newChild !== null) {
if (newChild.$$typeof === REACT_ELEMENT_TYPE) {
const created = createFiberFromElement(newChild, expirationTime);
created.return = returnFiber;
return created;
}
}
return null;
}
function deleteChild(returnFiber, childToDelete) {
if (!shouldTrackSideEffects) {
return;
}
// Deletion插入在末尾 ?
const last = returnFiber.lastEffect;
if (last) {
last.nextEffect = childToDelete;
returnFiber.lastEffect = childToDelete;
} else {
returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
}
childToDelete.nextEffect =

最低0.47元/天 解锁文章
717

被折叠的 条评论
为什么被折叠?



