1、存在问题
这里还存在一个问题,就是每次处理一个元素,都要向DOM添加一个新的节点,在完成整个树的渲染之前,由于做了可中断操作,那将看到一个不完整的UI,这样显然是不行的。
2、处理步骤
1.删除子节点添加到父节点的逻辑;
function performUnitOfWork(fiber) {
// 这段逻辑删了
if (fiber.parent) {
fiber.parent.dom.appendChild(fiber.dom)
}
}
2.添加fiber根节点wipRoot,并设置为下一个工作单元;
let wipRoot = null
export function render(element, container) {
// 将根节点设置为第一个工作单元
wipRoot = {
dom: container,
props: {
children: [element],
},
}
nextUnitOfWork = wipRoot
}
3.当完成了所有任务,也就是说没有下一个工作单元了,这时需要把整个fiber渲染为DOM;
// 提交任务,将fiber tree 渲染为真实 DOM
function commitRoot(){
}
function workLoop(deadline) {
// 省略
// 没有下一个工作单元,提交当前fiber树
if (!nextUnitOfWork && wipRoot) {
commitRoot()
}
// 省略
}
4.在 commitRoot 函数中执行提交工作,递归将所有节点附加到 dom 中;
/**
* 处理提交的fiber树
* @param {*} fiber
* @returns
*/
function commitWork(fiber){
if (!fiber) {
return
}
const domParent = fiber.parent.dom
// 将自己点添加到父节点下
domParent.appendChild(fiber.dom)
// 渲染子节点
commitWork(fiber.child)
// 渲染兄弟节点
commitWork(fiber.sibling)
}
/**
* 提交任务,将fiber tree 渲染为真实 DOM
*/
function commitRoot(){
commitWork(wipRoot.child)
wipRoot = null
}
3、运行结果
运行结果没有问题
4、本节代码
代码地址:https://github.com/linhexs/mini-react/tree/5.RenderAndCommit