前言
在React中会将我们写的组件转为jsx
的多叉树,最后转为fiber
树,他是如何转化的呢,今天我们一起探索下吧。
jsx多叉树
一个简单的jsx
对象有如下属性:
go
const jsx = {
type:'div',
key: 1,
}
// 其余的属性我们省略掉,暂时用不到
fiber
一个fiber
对象的简单属性有以下5个:
kotlin
const fiber = {
type: 'div', // 节点的类型
key: 1,
child: null, // 子Fiber节点
sibling: null, // 兄弟Fiber节点
return: null, // 父Fiber节点(在递归过程中设置)
};
实现
有如下一个jsx的多叉树,我们需要转为图二的fiber
树
- 图一,
- 图二
- 第一步:我们首先传入
jsx
根节点,创建出根节点对应的fiber
- 第二步:我们判断jsx根节点有没有children,如果有,那么我们遍历递归创建
childFiber
- 当创建好
childFiber
后,我们需要将childFiber.return
指向其父fiber
节点, - 其次我们还需要判断
childFiber
是不是第一个子节点,如果是设置fiber.child = childFiber;
- 如果不是第一个子节点,我们需要在遍历创建之前记录子节点的最后一个节点
lastChildFiber
,然后让lastChildFiber.siblings指向新创建的childFiber
- 当创建好
javascript
const createFiber = (jsxNode) => {
// 创建Fiber节点
const fiber = {
type: jsxNode.type, // JSX节点的类型
key: jsxNode.key,
child: null, // 子Fiber节点
return: null, // 兄弟Fiber节点
siblings: null, // 父Fiber节点(在递归过程中设置)
}
// 如果JSX节点有子节点,递归创建Fiber子树
if(jsxNode.children && jsxNode.children.length > 0) {
let lastChildFiber = null;
for(let i = 0; i < jsxNode.children.length; i++){
const childFiber = createFiber(jsxNode.children[i])
// 设置子Fiber节点的return属性指向当前Fiber节点
childFiber.return = fiber;
// 如果是第一个子节点,则设置为child属性
if(!fiber.child) {
fiber.child = childFiber
} else {
// 否则,将其设置为上一个子节点的sibling属性
lastChildFiber.next = childFiber
}
// 更新最后一个子节点的引用
lastChildFiber = childFiber
}
}
return fiber
}
- 上面这样,我们就实现了一个简单的将jsx树转为fiber树的算法。
- 后面我们会在此基础上实现react diff,以及可中断的diff.