image.png

    1. import elements from './element.js'
    2. // 目的: 把虚拟DOM渲染到根节点中
    3. let container = document.getElementById('root');
    4. const PLACEMENT = 'PLACEMENT';
    5. // 下一个工作单元
    6. // fiber对象其实也是一个普通的JS对象
    7. let workInProgressRoot = {
    8. stateNode: container, // 静态节点,fiber的真实DOM
    9. props: {children: [elements]}, // fiber的属性
    10. };
    11. let nextUnitOfWork = workInProgressRoot;
    12. function workLoop(){
    13. while(nextUnitOfWork){ // 下一个工作单元
    14. nextUnitOfWork = performUnitOfWork(nextUnitOfWork) // 返回下一个工作单元
    15. }
    16. if(!nextUnitOfWork){
    17. commitRoot()
    18. }
    19. }
    20. function commitRoot () {
    21. let currentFiber = workInProgressRoot.firstEffect;
    22. while(currentFiber){
    23. if(currentFiber.effectTag === PLACEMENT){
    24. console.log('commitRoot',currentFiber.return.stateNode)
    25. console.log('currentFiber.stateNode',currentFiber.stateNode)
    26. currentFiber.return.stateNode.appendChild(currentFiber.stateNode)
    27. }
    28. currentFiber = currentFiber.nextEffect;
    29. }
    30. workInProgressRoot = null;
    31. }
    32. function performUnitOfWork (workingInProgressFiber) { // workingInProgressFiber 正在工作中的fiber节点
    33. beginWork(workingInProgressFiber) // 创建真实DOM 创建fiber子节点, 不进行挂载
    34. if(workingInProgressFiber.child){ // 如果有子节点就返回
    35. return workingInProgressFiber.child
    36. }
    37. while(workingInProgressFiber){
    38. completeUnitOfWork(workingInProgressFiber)
    39. if(workingInProgressFiber.sibling){ // 如果有兄弟节点就返回
    40. return workingInProgressFiber.sibling
    41. }
    42. workingInProgressFiber = workingInProgressFiber.return // 如果都没有 指向父节点 重新寻找
    43. }
    44. }
    45. function beginWork (workingInProgressFiber){
    46. console.log('beginWork', workingInProgressFiber.props.id)
    47. // 创建真实DOM
    48. if(!workingInProgressFiber.stateNode){
    49. workingInProgressFiber.stateNode = document.createElement(workingInProgressFiber.type)
    50. for(let key in workingInProgressFiber.props){
    51. if(key !== 'children'){
    52. workingInProgressFiber.stateNode[key] = workingInProgressFiber.props[key];
    53. }
    54. }
    55. }
    56. // 创建子fiber
    57. let perviousFiber;
    58. if(Array.isArray(workingInProgressFiber.props.children)){
    59. workingInProgressFiber.props.children.forEach((child, index) =>{
    60. let childFiber ={
    61. type: child.type,
    62. props: child.props,
    63. return: workingInProgressFiber, //
    64. effectTag: PLACEMENT, // 副作用标记,表示这个节点要进行什么操作
    65. nextEffect: null // 下一个有副作用的节点
    66. }
    67. if(index === 0) {
    68. workingInProgressFiber.child = childFiber // 让父节点的child指向儿子
    69. } else {
    70. perviousFiber.sibling = childFiber;
    71. }
    72. perviousFiber = childFiber
    73. })
    74. }
    75. }
    76. function completeUnitOfWork (workingInProgressFiber) {
    77. console.log('completeUnitOfWork', workingInProgressFiber.props.id)
    78. // 构建副作用链,effectList,只有那些有副作用的节点
    79. let returnFiber = workingInProgressFiber.return; // A1
    80. if(returnFiber){ // 把子的副作用和自己的副作用都归到自己身上
    81. // 把当前fiber的有副作用子链表挂载到父亲身上
    82. if(!returnFiber.firstEffect){
    83. returnFiber.firstEffect = workingInProgressFiber.firstEffect
    84. }
    85. if(workingInProgressFiber.lastEffect){
    86. if(returnFiber.lastEffect){
    87. returnFiber.lastEffect.nextEffect = workingInProgressFiber.firstEffect
    88. }
    89. returnFiber.lastEffect = workingInProgressFiber.lastEffect;
    90. }
    91. // 再把自己挂到后边
    92. if(workingInProgressFiber.effectTag){
    93. if(returnFiber.lastEffect){
    94. returnFiber.lastEffect.nextEffect = workingInProgressFiber;
    95. } else {
    96. returnFiber.firstEffect = workingInProgressFiber
    97. }
    98. returnFiber.lastEffect = workingInProgressFiber;
    99. }
    100. }
    101. }
    102. // 告诉浏览器在每帧的空余时间调用工作循环
    103. requestIdleCallback(workLoop)