react diff原理

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 =

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值