React源码解析

109 阅读1分钟

1. react架构

调度层、协调层、渲染层三层

  • 调度层:调度任务的优先级,高优先级的任务优先进入协调层
  • 协调层:构建Fiber数据结构,对比Fiber对象找出差异,记录Fiber对象要进行的DOM操作
  • 渲染层:负责将发生变化的部分渲染到页面上

2. 实现思路

在Fiber方案中,为了实现任务的终止再继续,DOM比对算法分成了两部分:

  1. 构建 Fiber (可中断)
  2. 提交 Commit (不可中断)

DOM初始化渲染:virtualDOM -> Fiber(创建Fiber节点) -> Fiber[](Fiber节点存储到数组里) -> DOM

DOM更新操作:newFiber(重新创建Fiber节点) vs oldFiber -> Fiber[] -> DOM

循环 + 递归(递归是不可中断的) -> 改为只采用循环

virtualDOM树作为一个任务 -> 拆分为virtualDOM树的一个结点作为一个任务

3. Fiber对象

为JavaScript对象

{
	type  			节点类型(元素,文本,组件)
	props  			节点属性
	stateNode  	节点DOM对象 | 组件实例对象
	tag  		节点标记(hostRoot | hostComponent | classComponent | functionComponent)
	effects 		数组,存储需要更改的Fiber对象
	effectTag 	当前Fiber要执行的操作(新增,删除,修改)
	parent			当前Fiber的父级Fiber
	child				当前Fiber的子级Fiber
	sibling			当前Fiber的下一个兄弟Fiber
	alternate		Fiber备份,Fiber对比时使用
}

4. Fiber对象生成DOM

fiber.effects.forEach(item => {
  if(item.effectTag === "delete") {
    item.parent.stateNode.removeChild(item.stateNode)
  } else if(item.effectTag === "update") {
    if(item.type === item.alternate.type) {
     /**
      * 节点类型相同
      * item 新virtualDOM
      * item.alternate 旧virtualDOM
      */
      updateNodeElement(item.stateNode, item, item.alternate)
    } else {
     /**
      * 节点类型不同
      */
    	item.parent.stateNode.replaceChild(
        item.stateNode,
        item.alternate.stateNode
      )
    }
  } else if(item.effectTag === "placement") {
    item.parent.stateNode.append(item.stateNode)
  }
})