• 从顶点开始遍历
    • 如果有第一个儿子,先遍历第一个儿子
    • 如果没有第一个儿子,标志着此节点遍历完成
    • 如果有弟弟遍历弟弟
    • 如果有没有下一个弟弟,返回父节点标识完成父节点遍历,如果有叔叔遍历叔叔
    • 没有父节点遍历结束
    • 先儿子,后弟弟,再叔叔,辈份越小越优先
    • 什么时候一个节点遍历完成? 没有子节点,或者所有子节点都遍历完成了
    • 没爹了就表示全部遍历完成了

    image.png

    1. import element from './element'
    2. let container = document.getElementById('root'); // 1、把虚拟dom渲染道真实dom
    3. const PLACEMENT = 'PLACEMENT'
    4. // 3、下一个工作单元
    5. // 6fiber其实也是一个普通的JS对象
    6. let nextUnitOfWork = {
    7. stateNode: container, // 7、此fiber对应的DOM节点
    8. props: {children:[element]}, // 8fiber的属性
    9. // child, // 11fiber的数据结构
    10. // return,
    11. // sibling
    12. };
    13. function workLoop (deadline) { // 2 工作循环
    14. // 5、如果有当前的工作单元,就执行它,返回下一个工作单元
    15. while(nextUnitOfWork && deadline.timeRemaing() > 0){ //注释:新增判断deadline
    16. nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
    17. }
    18. }
    19. /**
    20. * 9
    21. * beginWork 1、创建此fiber的真实DOM,通过虚拟DOM创建fiber结构
    22. * @param {*} workingInProgressFiber
    23. */
    24. function performUnitOfWork(workingInProgressFiber) { // 注释:正在工作中的fiber
    25. // 101、创建真实DOM,但是并不挂载 2、创建fiber子树
    26. beginWork(workingInProgressFiber)
    27. if(workingInProgressFiber.child){
    28. return workingInProgressFiber.child // 11、如果有子元素返回子元素
    29. }
    30. while(workingInProgressFiber){
    31. // 14、如果没有儿子当前节点其实就结束完成了
    32. completeUnitOfWork(workingInProgressFiber)
    33. if(workingInProgressFiber.sibling){
    34. return workingInProgressFiber.sibling // 12、如果有兄弟元素返回兄弟元素
    35. }
    36. workingInProgressFiber = workingInProgressFiber.return // 13、先指向父虚拟节点,然后继续循环,找到了父虚拟节点的兄弟节点
    37. }
    38. }
    39. function beginWork(workingInProgressFiber){
    40. console.log('beginWork', workingInProgressFiber.props.id)
    41. // 注释:第一步要创建节点
    42. if(!workingInProgressFiber.container){
    43. workingInProgressFiber.stateNode = document.createElement(workingInProgressFiber.type) // 创建真实dom节点
    44. for(let key in workingInProgressFiber.props){
    45. if(key !== 'child'){
    46. workingInProgressFiber.stateNode[key] = workingInProgressFiber.props[key]
    47. }
    48. } // 16、注意,在beginWork中不会进行挂载,下面创建fiber
    49. }
    50. let perviousFiber;
    51. workingInProgressFiber.props.children.forEach((child, index)=>{ // 注释:注意这里是一个虚拟DOM的数组,我们需要把虚拟DOM变成fiber
    52. let childFiber = {
    53. type: child.type,
    54. props: child.props,
    55. return: workingInProgressFiber, // 注释:为什么叫return,这里有返回的意思所以要return,要让父亲完成
    56. effecTag: PLACEMENT, // 17、副作用Tag标记,这个fiber对应的DOM节点需要被插入到父dom
    57. nextEffect: null // 注释:先不讲,下一个有副作用的节点
    58. }
    59. if(index === 0){ // 注释:索引为0意味着他是大儿子,所以要赋值
    60. workingInProgressFiber.child = childFiber
    61. } else {
    62. perviousFiber.sibling = childFiber;
    63. }
    64. perviousFiber = childFiber
    65. })
    66. }
    67. function completeUnitOfWork(workingInProgressFiber){ // 注释:完成工作循环
    68. console.log('completeUnitOfWork', workingInProgressFiber.props.id)
    69. // 18、构建副作用链条effectList,只有那些有副作用的节点
    70. }
    71. // 4、告诉浏览器在空闲的时候运行workLoop
    72. requestIdleCallback(workLoop)