前言
上一篇介绍了react-dom,再往后面写很多都是在操作FiberRoot和Fiber这两个数据结构,这里简单的介绍一下,另外希望大家可以把他当成一个普通的数据结构来看,暂时不要把它跟react里面的各种逻辑结合到一起学习,看不懂的属性就过,就当它有这么个属性就可以了
fiber数据结构
- 整个fiber是个单链表的属性结构
- 根FiberRoot
- 通过current指向一个FiberNode,这个current也称为RootFiber,是一个HostRoot类型fiber,也是所有fiber节点的根
- 每个Fiber节点通过child指向下一个Fiber节点
- Fiber节点中在通过return指向父节点
- 通过sibling指向兄弟节点
其实就是几个指针指来指去,如果这里就看不懂,可以去看看我很早以前写的一些数据结构的文章哈
FiberNode
Fiber
一个Fiber的初始化代码
class FiberNode {
constructor(tag, pendingProps, key, mode) {
// 实例属性
this.tag = tag; // 标记不同组件类型,如classComponent,functionComponent
this.key = key; // react元素上的key 就是jsx上写的那个key,也就是最终ReactElement上的
this.elementType = null; // createElement的第一个参数,ReactElement上的type
this.type = null; // 表示fiber的真实类型 ,elementType基本一样,在使用了懒加载之类的功能时可能会不一样
this.stateNode = null; // 实例对象,比如class组件new完后就挂载在这个属性上面,如果是RootFiber,那么它上面挂的是FiberRoot
// fiber
this.return = null; // 父节点,指向上一个fiber
this.child = null; // 子节点,指向自身下面的第一个fiber
this.sibling = null; // 兄弟组件, 指向一个兄弟节点
this.index = 0; // 一般如果没有兄弟节点的话是0 当某个父节点下的子节点是数组类型的时候会给每个子节点一个index,index和key要一起做diff
this.ref = null; // reactElement上的ref属性
this.pendingProps = pendingProps; // 新的props
this.memoizedProps = null; // 旧的props
this.updateQueue = null; // fiber上的更新队列 执行一次setState就会往这个属性上挂一个新的更新, 每条更新最终会形成一个链表结构,最后做批量更新
this.memoizedState = null; // 对应memoizedProps,上次渲染的state,相当于当前的state,理解成prev和next的关系
this.mode = mode; // 表示当前组件下的子组件的渲染方式
// effects
this.effectTag = NoEffect; // 表示当前fiber要进行何种更新
this.nextEffect = null; // 指向下个需要更新的fiber
this.firstEffect = null; // 指向所有子节点里,需要更新的fiber里的第一个
this.lastEffect = null; // 指向所有子节点中需要更新的fiber的最后一个
this.expirationTime = NoWork; // 过期时间,代表任务在未来的哪个时间点应该被完成
this.childExpirationTime = NoWork; // child过期时间
this.alternate = null; // current树和workInprogress树之间的相互引用
}
}
- 以上就是整个fiber的初始化属性,其中跟结构有关系的就三个属性
- return: 父节点,指向上一个fiber
- child : 子节点,指向自身下面的第一个fiber
- sibling : 兄弟组件, 指向一个兄弟节点
-
它的遍历过程:
- 从current(Root)开始通过child向下找
- 如果有child先遍历子节点,直到null为止
- 然后看是否有兄弟节点
- 有兄弟节点则遍历兄弟节点
- 然后再看兄弟节点是否有子节点
- 然后return看父节点是否有兄弟节点
- 直到root
下面是我随意写的时候直接打的一段遍历伪代码,随便看看
function mountFiberRecursively(fiber){
if(fiber.child !== null){
mountFiberRecursively(fiber.child)
}
if(fiber.sibling !== null){
mountFiberRecursively(fiber.sibling);
return;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。