虚拟dom转化成fiber后,会有这几个属性,去指向下一个执行单元。
<div id="A1">
<div id="B1">
<div id="C1"></div>
<div id="C2"></div>
</div>
<div id="B2"></div>
<div>
这样的jsx如果要转成fiber则会是这个样子
详情可以戳 -> 在react中,虚拟dom是如何转化为fiber链表的?
// element.js
let A1 = { key: 'A1', type: 'div' }
let B1 = { key: 'B1', type: 'div', return: A1 }
let B2 = { key: 'B2', type: 'div', return: A1 }
let C1 = { key: 'C1', type: 'div', return: B1 }
let C2 = { key: 'C2', type: 'div', return: B1 }
A1.child = B1
B1.sibling = B2
B1.child = C1
C1.sibling = C2
module.exports = A1
fiber的遍历顺序是由根节点开始的,优先级 child > sibling > return
所以遍历的先后顺序是
开始遍历
let rootFiber = require('./element')
let nextUnitOfWork = null
function workLoop() {
while(nextUnitOfWork) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
}
}
function performUnitOfWork(currentFiber) { // 返回下一个执行单元
beginWork(currentFiber)
if (currentFiber.child) {
return currentFiber.child
}
// 如果能走到这一步,证明遍历到 C1 了
while(currentFiber) { // 因为此处可能 sibling不一定只有一个,所以要进入while循环
if(currentFiber.sibling) {
return currentFiber.sibling
}
// 如果没有sibling了,就会到其父节点
return currentFiber.return
}
}
function beginWork(currentFiber) {
// 本章主要记录fiber是怎么遍历的,所以就不去做别的事情啦
console.log(currentFiber.key)
}
nextUnitOfWork = rootFiber
workLoop()
function workLoop(deadline) {
// timeRemaining() 是指当前渲染完留给react调度的时间
while ((deadline.timeRemaining() > 1 && nextUnitOfWork) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
}
if (!nextUnitOfWork) {
console.log('render阶段遍历结束')
} else {
requestIdleCallback(workLoop, { timeout: 500 });
}
}
requestIdleCallback(workLoop, { timeout: 500 });