2. diff-删除多余的老节点

26 阅读1分钟

本节课我们去实现一下更新中的另外一个场景,当新的节点比老的短,多出来的节点需要删除掉。

构建例子App.tsx

  • 发现点击之后child没有删除

1.png

通过图去理解

2.png

  • 新的节点链表多出来了但是没处理

额外去处理一下,检测处理完之后有没有额外的孩子节点

  • 如果有则删除

先打印一下oldFiber,发现oldFiber的dom就是需要删除的节点

function initChildren(fiber, children) {
    let oldFiber = fiber.alternate?.child
    let prevChild = null
    children.forEach((child, index) => {
        const isSameType = oldFiber && oldFiber.type === child.type
        let newFiber
        if (isSameType) {
            //update
            newFiber = {
                type: child.type,
                props: child.props,
                child: null,
                parent: fiber,
                sibling: null,
                dom: oldFiber.dom,
                effectTag: "update",
                alternate: oldFiber
            }
        } else {
            newFiber = {
                type: child.type,
                props: child.props,
                child: null,
                parent: fiber,
                sibling: null,
                dom: null,
                effectTag: "placement"
            }
            if (oldFiber) {
                deletions.push(oldFiber)
            }
        }
​
        if (oldFiber) {
            oldFiber = oldFiber.sibling
        }
​
        if (index === 0) {
            fiber.child = newFiber
        } else {
            prevChild.sibling = newFiber
        }
        prevChild = newFiber
    })
    console.log(`oldFiber fff`, oldFiber)
}
​

3.png

加入删除

function initChildren(fiber, children) {
    // ...
    if(oldFiber) {
        deletions.push(oldFiber)
    }
}

处理有两个子节点的场景

  • 创建两个子节点app.tsx,child2没有被删除
  const Foo = <div>
    foo
    <div>child1</div>
    <div>child2</div>
  </div>
  const Bar = <div>bar</div>tsx

变成While循环,找到所有多的节点

function initChildren(fiber, children) {
    // ...
    while (oldFiber) {
        deletions.push(oldFiber)
        oldFiber = oldFiber.sibling
    }
}