fiber架构(简易代码)

2021-05-27  本文已影响0人  Mr无愧于心
let element = {
    type:'div',
    props:{
        id: 'A1',
        children: [
            {
                type:'div',
                props:{ 
                    id: 'B1',
                    children: [
                        { type:'div',props:{id: 'C1', children: []} },
                        { type:'div',props:{id: 'C2', children: []} },
                    ]
                },
            },
            {
                type:'div',props:{id: "B2", children: []}
            }
        ]
    },
}
let container=document.getElementById('container')
//第一个工作单元
let workInProgressRoot={
    stateNode:container,
    props:{children:[element]}//fiber的属性
};

// 下一个fiber工作单元
let nextUnitOfWork=workInProgressRoot;
function workLoop(){
    // 如果有当前的工作单元,就执行他,并返回一个工作单元
    while(nextUnitOfWork){
        nextUnitOfWork=performUnitOfWork(nextUnitOfWork);
    }
    if(!nextUnitOfWork){
        commitRoot()
    }
};
function commitRoot(){
    let currentFiber=workInProgressRoot.firstEffect;
    while(currentFiber){
        if(currentFiber.effectTag==='PLACEMENT'){
            currentFiber.return.stateNode.appendChild(currentFiber.stateNode);
        }
        currentFiber=currentFiber.nextEffect;
    }
}
// beginWork 创建此fiber的真实dom 通过虚拟dom创建fiber树结构
function performUnitOfWork(wordInProgressFiber){
    beginWork(wordInProgressFiber)// 创建fiber单元
    if(wordInProgressFiber.child){
        return wordInProgressFiber.child// 如果有儿子就返回儿子
    }

    while(wordInProgressFiber){
        //如果没有儿子当前节点就结束完成了
        completeUnitOfWork(wordInProgressFiber)
        if(wordInProgressFiber.sibling){//如果有弟弟,返回弟弟
            return wordInProgressFiber.sibling
        }
        wordInProgressFiber=wordInProgressFiber.return;// 先指向父亲,再循环取到叔叔
    }
}

function beginWork(wordInProgressFiber){
    console.log('beginWork',wordInProgressFiber.props.id)
    if(!wordInProgressFiber.stateNode){
        wordInProgressFiber.stateNode=document.createElement(wordInProgressFiber.type);
        for(let key in wordInProgressFiber.props){
            if(key !=='children'){
                wordInProgressFiber.stateNode[key]=wordInProgressFiber.props[key];
            }
        }
    }// 在beginWork中不会挂载dom元素
    //创建子fiber
    let previousFiber=null;
    wordInProgressFiber.props.children.forEach((child,index) => {
        let childFiber={
            type:child.type,// dom节点类型
            props:child.props,
            return:wordInProgressFiber,//父fiber
            effectTag:'PLACEMENT',// 副作用:表示这个fiber对应的dom节点需要被插入到页面中去 父dom中
        }
        if(index===0){
            wordInProgressFiber.child=childFiber
        }else{
            previousFiber.sibling=childFiber
        }
        previousFiber=childFiber
    });
}

function completeUnitOfWork(wordInProgressFiber){
    console.log('completeUnitOfWork',wordInProgressFiber.props.id);
    // 构建副作用链effectList 只有哪些有副作用的节点
    let returnFiber = wordInProgressFiber.return;
    if(returnFiber){
        // 把当前fiber的有副作用子链表挂载到父亲身上
        if(!returnFiber.firstEffect){
            returnFiber.firstEffect=wordInProgressFiber.firstEffect;
        }
        if(wordInProgressFiber.lastEffect){
            if(returnFiber.lastEffect){
                returnFiber.lastEffect.nextEffect=wordInProgressFiber.firstEffect 
            }
            returnFiber.lastEffect=wordInProgressFiber.lastEffect;
        }
        //再把自己挂到后面
        if(wordInProgressFiber.effectTag){
            if(returnFiber.lastEffect){
                returnFiber.lastEffect.nextEffect=wordInProgressFiber 
            }else{
                returnFiber.firstEffect=wordInProgressFiber;
            }
            returnFiber.lastEffect=wordInProgressFiber;
        }

    }
}


requestIdleCallback(workLoop)
上一篇下一篇

猜你喜欢

热点阅读