-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
diff #8
Comments
在这个diff函数中,旧的children是一个链表,新children是一个数组。for循环会开始同时对比新旧两个children。 第一个for循环专门const一个变量 function updateSlot(
returnFiber: Fiber,
oldFiber: Fiber | null,
newChild: any,
expirationTime: ExpirationTime,
): Fiber | null {
// Update the fiber if the keys match, otherwise return null.
const key = oldFiber !== null ? oldFiber.key : null;
if (typeof newChild === 'string' || typeof newChild === 'number') {
// Text nodes don't have keys. If the previous node is implicitly keyed
// we can continue to replace it without aborting even if it is not a text
// node.
if (key !== null) {
return null;
}
return updateTextNode(
returnFiber,
oldFiber,
'' + newChild,
expirationTime,
);
}
if (typeof newChild === 'object' && newChild !== null) {
//....
}
//....
} 函数挺长的,就不全部贴了,其实很轻松能通过最前面的注释了解到用途,主要是通过key来比对是否可以复用。
如果一旦第一个for循环中的child不可以复用的话,直接打断for循环。也不管后续的遍历。(其实这里我比较疑惑的是万一后续的可以复用呢?) 在这里第一轮遍历的结果有这么几个情况
第二次for循环新节点还没遍历完全,且老节点已经一滴也没有了,那么进入第二次for循环。直接把剩余新节点遍历,创建一个个新的fiber然后插入就行,最终也是return出一个结果。 第三次for循环如果上面两个return的判断都走不进去,那么就是第三次遍历循环。核心逻辑是找出可以复用的老节点并移动位置。 <p key={1}>1</p>
<p key={2}>2</p> 那么这个 map 的结构就会是这样的: // 节点的 key 作为 map 的 key
// 如果节点不存在 key,那么 index 为 key
const map = {
1: {},
2: {}
} 在遍历的过程中会寻找新的节点的 key 是否存在于这个 map 中,存在即可复用,不存在就只能创建一个新的了。 此轮遍历结束后,就把还存在于 map 中的所有老节点删除。 总结下:
其实这个和15版的diff最终体现其实都是那么几个步骤:插入,删除,移动。 |
The text was updated successfully, but these errors were encountered: