04.lane模型下的更新队列
react-reconciler/src/ReactFiberClassUpdateQueue.js
js
import { enqueueConcurrentClassUpdate } from "./ReactFiberConcurrentUpdates";
import assign from "shared/assign";
import { NoLanes, mergeLanes, isSubsetOfLanes } from './ReactFiberLane';
export const UpdateState = 0;
/**
* 初始化更新队列
* @param {Object} fiber - 对应的fiber对象
*/
export function initialUpdateQueue(fiber) {
const queue = {
baseState: fiber.memoizedState,
firstBaseUpdate: null,
lastBaseUpdate: null,
shared: {
pending: null,
},
};
fiber.updateQueue = queue;
}
/**
* 创建更新对象
* @param {number} lane - 车道信息
* @returns {Object} update - 返回一个新的更新对象
*/
export function createUpdate(lane) {
const update = { tag: UpdateState, lane, next: null };
return update;
}
/**
* 将更新加入队列
* @param {Object} fiber - fiber对象
* @param {Object} update - 更新对象
* @param {number} lane - 车道信息
* @returns {Object} 更新后的fiber对象
*/
export function enqueueUpdate(fiber, update, lane) {
const updateQueue = fiber.updateQueue;
const sharedQueue = updateQueue.shared;
return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane);
}
/**
* 处理更新队列
* @param {Object} workInProgress - 当前工作的fiber
* @param {*} nextProps - 下一个属性集合
* @param {*} renderLanes - 渲染车道
*/
export function processUpdateQueue(workInProgress, nextProps, renderLanes) {
const queue = workInProgress.updateQueue;
let firstBaseUpdate = queue.firstBaseUpdate;
let lastBaseUpdate = queue.lastBaseUpdate;
const pendingQueue = queue.shared.pending;
if (pendingQueue !== null) {
queue.shared.pending = null;
const lastPendingUpdate = pendingQueue;
const firstPendingUpdate = lastPendingUpdate.next;
lastPendingUpdate.next = null;
if (lastBaseUpdate === null) {
firstBaseUpdate = firstPendingUpdate;
} else {
lastBaseUpdate.next = firstPendingUpdate;
}
lastBaseUpdate = lastPendingUpdate;
}
if (firstBaseUpdate !== null) {
let newState = queue.baseState;
let newLanes = NoLanes;
let newBaseState = null;
let newFirstBaseUpdate = null;
let newLastBaseUpdate = null;
let update = firstBaseUpdate;
do {
const updateLane = update.lane;
if (!isSubsetOfLanes(renderLanes, updateLane)) {
const clone = {
id: update.id,
lane: updateLane,
payload: update.payload
};
if (newLastBaseUpdate === null) {
newFirstBaseUpdate = newLastBaseUpdate = clone;
newBaseState = newState;
} else {
newLastBaseUpdate = newLastBaseUpdate.next = clone;
}
newLanes = mergeLanes(newLanes, updateLane);
} else {
if (newLastBaseUpdate !== null) {
const clone = {
id: update.id,
lane: 0,
payload: update.payload
};
newLastBaseUpdate = newLastBaseUpdate.next = clone;
}
newState = getStateFromUpdate(update, newState);
}
update = update.next;
} while (update);
if (!newLastBaseUpdate) {
newBaseState = newState;
}
queue.baseState = newBaseState;
queue.firstBaseUpdate = newFirstBaseUpdate;
queue.lastBaseUpdate = newLastBaseUpdate;
workInProgress.lanes = newLanes;
workInProgress.memoizedState = newState;
}
}
/**
* 根据更新计算新状态
* @private
* @param {Object} update - 更新对象
* @param {*} prevState - 上一个状态
* @param {*} nextProps - 下一个属性集合
* @returns {*} 新的状态
*/
function getStateFromUpdate(update, prevState, nextProps) {
switch (update.tag) {
case UpdateState:
const { payload } = update;
let partialState;
if (typeof payload === 'function') {
partialState = payload.call(null, prevState, nextProps);
} else {
partialState = payload;
}
return assign({}, prevState, partialState);
}
}
/**
* 克隆更新队列
* @param {Object} current - 当前状态下的fiber对象
* @param {Object} workInProgress - 正在工作的fiber对象
*/
export function cloneUpdateQueue(current, workInProgress) {
const workInProgressQueue = workInProgress.updateQueue;
const currentQueue = current.updateQueue;
if (currentQueue === workInProgressQueue) {
const clone = {
baseState: currentQueue.baseState,
firstBaseUpdate: currentQueue.firstBaseUpdate,
lastBaseUpdate: currentQueue.lastBaseUpdate,
shared: currentQueue.shared
};
workInProgress.updateQueue = clone;
}
}react-reconciler/src/ReactFiberConcurrentUpdates.js
js
import { HostRoot } from "./ReactWorkTags";
// 并发队列数组
const concurrentQueues = [];
// 并发队列索引
let concurrentQueuesIndex = 0;
/**
* 将更新加入并发队列
* @param {Object} fiber - fiber对象
* @param {Object} queue - 更新队列
* @param {Object} update - 更新对象
* @param {number} lane - 车道信息
*/
function enqueueUpdate(fiber, queue, update, lane) {
concurrentQueues[concurrentQueuesIndex++] = fiber;
concurrentQueues[concurrentQueuesIndex++] = queue;
concurrentQueues[concurrentQueuesIndex++] = update;
concurrentQueues[concurrentQueuesIndex++] = lane;
}
/**
* 完成并发更新的排队
*/
export function finishQueueingConcurrentUpdates() {
const endIndex = concurrentQueuesIndex;
concurrentQueuesIndex = 0;
let i = 0;
while (i < endIndex) {
const fiber = concurrentQueues[i++];
const queue = concurrentQueues[i++];
const update = concurrentQueues[i++];
const lane = concurrentQueues[i++];
if (queue !== null && update !== null) {
const pending = queue.pending;
if (pending === null) {
update.next = update;
} else {
update.next = pending.next;
pending.next = update;
}
queue.pending = update;
}
}
}
/**
* 将钩子更新加入并发队列
* @param {Object} fiber - fiber对象
* @param {Object} queue - 更新队列
* @param {Object} update - 更新对象
* @param {number} lane - 车道信息
* @returns {Object|null} 更新的fiber的根,如果不存在则返回null
*/
export function enqueueConcurrentHookUpdate(fiber, queue, update, lane) {
enqueueUpdate(fiber, queue, update, lane);
return getRootForUpdatedFiber(fiber);
}
/**
* 将类组件更新加入并发队列
* @param {Object} fiber - fiber对象
* @param {Object} queue - 更新队列
* @param {Object} update - 更新对象
* @param {number} lane - 车道信息
* @returns {Object|null} 更新的fiber的根,如果不存在则返回null
*/
export function enqueueConcurrentClassUpdate(fiber, queue, update, lane) {
enqueueUpdate(fiber, queue, update, lane);
return getRootForUpdatedFiber(fiber);
}
/**
* 获取更新的fiber的根节点
* @private
* @param {Object} sourceFiber - 源fiber节点
* @returns {Object|null} fiber的根节点,如果不存在则返回null
*/
function getRootForUpdatedFiber(sourceFiber) {
let node = sourceFiber;
let parent = node.return;
while (parent !== null) {
node = parent;
parent = node.return;
}
return node.tag === HostRoot ? node.stateNode : null;
}