import { setProps } from './utils';import { ELEMENT_TEXT, TAG_ROOT, TAG_HOST, TAG_TEXT, PLACEMENT} from './constants';let workInProgressRoot = null;//正在渲染中的根Fiberlet nextUnitOfWork = null//下一个工作单元export function scheduleRoot(rootFiber) { //把当前树设置为nextUnitOfWork开始进行调度 workInProgressRoot = rootFiber; nextUnitOfWork = workInProgressRoot;}function commitRoot() { let currentFiber = workInProgressRoot.firstEffect; while (currentFiber) { commitWork(currentFiber); currentFiber = currentFiber.nextEffect; } workInProgressRoot = null;}function commitWork(currentFiber) { if (!currentFiber) { return; } let returnFiber = currentFiber.return;//先获取父Fiber const domReturn = returnFiber.stateNode;//获取父的DOM节点 if (currentFiber.effectTag === PLACEMENT && currentFiber.stateNode != null) {//如果是新增DOM节点 let nextFiber = currentFiber; domReturn.appendChild(nextFiber.stateNode); } currentFiber.effectTag = null;}function performUnitOfWork(currentFiber) { beginWork(currentFiber);//开始渲染前的Fiber,就是把子元素变成子fiber if (currentFiber.child) {//如果子节点就返回第一个子节点 return currentFiber.child; } while (currentFiber) {//如果没有子节点说明当前节点已经完成了渲染工作 completeUnitOfWork(currentFiber);//可以结束此fiber的渲染了 if (currentFiber.sibling) {//如果它有弟弟就返回弟弟 return currentFiber.sibling; } currentFiber = currentFiber.return;//如果没有弟弟让爸爸完成,然后找叔叔 }}function beginWork(currentFiber) { if (currentFiber.tag === TAG_ROOT) {//如果是根节点 updateHostRoot(currentFiber); } else if (currentFiber.tag === TAG_TEXT) {//如果是原生文本节点 updateHostText(currentFiber); } else if (currentFiber.tag === TAG_HOST) {//如果是原生DOM节点 updateHostComponent(currentFiber); }}function updateHostRoot(currentFiber) {//如果是根节点 const newChildren = currentFiber.props.children;//直接渲染子节点 reconcileChildren(currentFiber, newChildren);}function updateHostText(currentFiber) { if (!currentFiber.stateNode) { currentFiber.stateNode = createDOM(currentFiber);//先创建真实的DOM节点 }}function updateHostComponent(currentFiber) {//如果是原生DOM节点 if (!currentFiber.stateNode) { currentFiber.stateNode = createDOM(currentFiber);//先创建真实的DOM节点 } const newChildren = currentFiber.props.children; reconcileChildren(currentFiber, newChildren);}function createDOM(currentFiber) { if (currentFiber.type === ELEMENT_TEXT) { return document.createTextNode(currentFiber.props.text); } const stateNode = document.createElement(currentFiber.type); updateDOM(stateNode, {}, currentFiber.props); return stateNode;}function reconcileChildren(currentFiber, newChildren) { let newChildIndex = 0;//新虚拟DOM数组中的索引 let prevSibling; while (newChildIndex < newChildren.length) { const newChild = newChildren[newChildIndex]; let tag; if (newChild && newChild.type === ELEMENT_TEXT) { tag = TAG_TEXT;//文本 } else if (newChild && typeof newChild.type === 'string') { tag = TAG_HOST;//原生DOM组件 } let newFiber = { tag,//原生DOM组件 type: newChild.type,//具体的元素类型 props: newChild.props,//新的属性对象 stateNode: null,//stateNode肯定是空的 return: currentFiber,//父Fiber effectTag: PLACEMENT,//副作用标识 nextEffect: null } if (newFiber) { if (newChildIndex === 0) { currentFiber.child = newFiber;//第一个子节点挂到父节点的child属性上 } else { prevSibling.sibling = newFiber; } prevSibling = newFiber;//然后newFiber变成了上一个哥哥了 } prevSibling = newFiber;//然后newFiber变成了上一个哥哥了 newChildIndex++; }}function updateDOM(stateNode, oldProps, newProps) { setProps(stateNode, oldProps, newProps);}function completeUnitOfWork(currentFiber) { const returnFiber = currentFiber.return; if (returnFiber) { if (!returnFiber.firstEffect) { returnFiber.firstEffect = currentFiber.firstEffect; } if (!!currentFiber.lastEffect) { if (!!returnFiber.lastEffect) { returnFiber.lastEffect.nextEffect = currentFiber.firstEffect; } returnFiber.lastEffect = currentFiber.lastEffect; } const effectTag = currentFiber.effectTag; if (effectTag) { if (!!returnFiber.lastEffect) { returnFiber.lastEffect.nextEffect = currentFiber; } else { returnFiber.firstEffect = currentFiber; } returnFiber.lastEffect = currentFiber; } }}function workLoop(deadline) { let shouldYield = false; while (nextUnitOfWork && !shouldYield) { nextUnitOfWork = performUnitOfWork(nextUnitOfWork);//执行一个任务并返回下一个任务 shouldYield = deadline.timeRemaining() < 1;//如果剩余时间小于1毫秒就说明没有时间了,需要把控制权让给浏览器 } //如果没有下一个执行单元了,并且当前渲染树存在,则进行提交阶段 if (!nextUnitOfWork && workInProgressRoot) { commitRoot(); } requestIdleCallback(workLoop);}//开始在空闲时间执行workLooprequestIdleCallback(workLoop);