Match-id-fa22e32139c3b08f8277784897028d35166c0e95
This commit is contained in:
parent
bd50434e32
commit
4759e65160
|
@ -1,5 +1,5 @@
|
||||||
import type {VNode} from './Types';
|
import type { VNode } from './Types';
|
||||||
import type {Update} from './UpdateHandler';
|
import type { Update } from './UpdateHandler';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
asyncUpdates,
|
asyncUpdates,
|
||||||
|
@ -7,12 +7,12 @@ import {
|
||||||
runDiscreteUpdates,
|
runDiscreteUpdates,
|
||||||
launchUpdateFromVNode,
|
launchUpdateFromVNode,
|
||||||
} from './TreeBuilder';
|
} from './TreeBuilder';
|
||||||
import {runAsyncEffects} from './submit/HookEffectHandler';
|
import { runAsyncEffects } from './submit/HookEffectHandler';
|
||||||
import {Callback, newUpdate, pushUpdate} from './UpdateHandler';
|
import { Callback, newUpdate, pushUpdate } from './UpdateHandler';
|
||||||
import {getFirstChild} from './vnode/VNodeUtils';
|
import { getFirstChild } from './vnode/VNodeUtils';
|
||||||
|
|
||||||
export {createVNode} from './vnode/VNodeCreator';
|
export { createVNode } from './vnode/VNodeCreator';
|
||||||
export {createPortal} from './components/CreatePortal';
|
export { createPortal } from './components/CreatePortal';
|
||||||
export {
|
export {
|
||||||
asyncUpdates,
|
asyncUpdates,
|
||||||
syncUpdates,
|
syncUpdates,
|
||||||
|
@ -26,7 +26,7 @@ export function startUpdate(
|
||||||
callback?: Callback,
|
callback?: Callback,
|
||||||
) {
|
) {
|
||||||
const update: Update = newUpdate();
|
const update: Update = newUpdate();
|
||||||
update.content = {element};
|
update.content = { element };
|
||||||
|
|
||||||
if (typeof callback === 'function') {
|
if (typeof callback === 'function') {
|
||||||
update.callback = callback;
|
update.callback = callback;
|
||||||
|
@ -38,10 +38,9 @@ export function startUpdate(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFirstCustomDom(treeRoot: VNode): Element | Text | null {
|
export function getFirstCustomDom(treeRoot: VNode): Element | Text | null {
|
||||||
if (!treeRoot.child) {
|
if (treeRoot?.child) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return treeRoot.child.realNode;
|
return treeRoot.child.realNode;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import type {VNode} from './Types';
|
import type { VNode } from './Types';
|
||||||
|
|
||||||
import {callRenderQueueImmediate, pushRenderCallback} from './taskExecutor/RenderQueue';
|
import { callRenderQueueImmediate, pushRenderCallback } from './taskExecutor/RenderQueue';
|
||||||
import {updateVNode} from './vnode/VNodeCreator';
|
import { updateVNode } from './vnode/VNodeCreator';
|
||||||
import {TreeRoot} from './vnode/VNodeTags';
|
import { TreeRoot } from './vnode/VNodeTags';
|
||||||
import {FlagUtils} from './vnode/VNodeFlags';
|
import { FlagUtils } from './vnode/VNodeFlags';
|
||||||
import {captureVNode} from './render/BaseComponent';
|
import { captureVNode } from './render/BaseComponent';
|
||||||
import {checkLoopingUpdateLimit, submitToRender} from './submit/Submit';
|
import { checkLoopingUpdateLimit, submitToRender } from './submit/Submit';
|
||||||
import {runAsyncEffects} from './submit/HookEffectHandler';
|
import { runAsyncEffects } from './submit/HookEffectHandler';
|
||||||
import {handleRenderThrowError} from './ErrorHandler';
|
import { handleRenderThrowError } from './ErrorHandler';
|
||||||
import componentRenders from './render';
|
import componentRenders from './render';
|
||||||
import ProcessingVNode from './vnode/ProcessingVNode';
|
import ProcessingVNode from './vnode/ProcessingVNode';
|
||||||
import {findDomParent, getSiblingVNode} from './vnode/VNodeUtils';
|
import { findDomParent, getSiblingVNode } from './vnode/VNodeUtils';
|
||||||
import {
|
import {
|
||||||
ByAsync,
|
ByAsync,
|
||||||
BySync,
|
BySync,
|
||||||
|
@ -21,7 +21,7 @@ import {
|
||||||
isExecuting,
|
isExecuting,
|
||||||
setExecuteMode
|
setExecuteMode
|
||||||
} from './ExecuteMode';
|
} from './ExecuteMode';
|
||||||
import {recoverParentsContextCtx, resetNamespaceCtx, setNamespaceCtx} from './ContextSaver';
|
import { recoverParentsContextCtx, resetNamespaceCtx, setNamespaceCtx } from './ContextSaver';
|
||||||
import {
|
import {
|
||||||
updateChildShouldUpdate,
|
updateChildShouldUpdate,
|
||||||
updateParentsChildShouldUpdate,
|
updateParentsChildShouldUpdate,
|
||||||
|
@ -61,132 +61,6 @@ export function setStartVNode(vNode: VNode | null) {
|
||||||
startVNode = vNode;
|
startVNode = vNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发起更新
|
|
||||||
export function launchUpdateFromVNode(vNode: VNode) {
|
|
||||||
// 检查循环调用
|
|
||||||
checkLoopingUpdateLimit();
|
|
||||||
|
|
||||||
// 从当前vNode向上遍历到根节点,修改vNode.shouldUpdate和parent.childShouldUpdate
|
|
||||||
const treeRoot = updateShouldUpdateOfTree(vNode);
|
|
||||||
if (treeRoot === null) {
|
|
||||||
// 可能场景是:the componentWillUnmount method 或 useEffect cleanup function 方法中写异步任务,并且修改state。
|
|
||||||
// 因为异步回调的时候root都可能被清除了。
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存待刷新的节点
|
|
||||||
treeRoot.toUpdateNodes.add(vNode);
|
|
||||||
|
|
||||||
if (checkMode(BySync) && // 非批量
|
|
||||||
!checkMode(InRender)) { // 不是渲染阶段触发
|
|
||||||
|
|
||||||
// 业务直接调用Horizon.render的时候会进入这个分支,同步渲染。
|
|
||||||
// 不能改成下面的异步,否则会有时序问题,因为业务可能会依赖这个渲染的完成。
|
|
||||||
renderFromRoot(treeRoot);
|
|
||||||
} else {
|
|
||||||
tryRenderRoot(treeRoot);
|
|
||||||
|
|
||||||
if (!isExecuting()) {
|
|
||||||
// 同步执行
|
|
||||||
callRenderQueueImmediate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从多个更新节点中,计算出开始节点。即:找到最近的共同的父辈节点
|
|
||||||
export function calcStartUpdateVNode(treeRoot: VNode) {
|
|
||||||
const toUpdateNodes = Array.from(treeRoot.toUpdateNodes);
|
|
||||||
|
|
||||||
if (toUpdateNodes.length === 0) {
|
|
||||||
return treeRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toUpdateNodes.length === 1) {
|
|
||||||
return toUpdateNodes[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 要计算的节点过多,直接返回根节点
|
|
||||||
if (toUpdateNodes.length > 100) {
|
|
||||||
return treeRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 找到路径最短的长度
|
|
||||||
let minPath = toUpdateNodes[0].path.length;
|
|
||||||
for (let i = 1; i < toUpdateNodes.length; i++) {
|
|
||||||
let pathLen = toUpdateNodes[i].path.length;
|
|
||||||
if (pathLen < minPath) {
|
|
||||||
minPath = pathLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 找出开始不相等的idx
|
|
||||||
let idx = 0;
|
|
||||||
for (; idx < minPath; idx++) {
|
|
||||||
if (!isEqualByIndex(idx, toUpdateNodes)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 得到相等的路径
|
|
||||||
let startNodePath = toUpdateNodes[0].path.slice(0, idx);
|
|
||||||
|
|
||||||
let node = treeRoot;
|
|
||||||
for (let i = 1; i < startNodePath.length; i++) {
|
|
||||||
let pathIndex = startNodePath[i];
|
|
||||||
node = getChildByIndex(node, pathIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getChildByIndex(vNode: VNode, idx: number) {
|
|
||||||
let node = vNode.child;
|
|
||||||
for (let i = 0; i < idx; i++) {
|
|
||||||
node = node.next;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断数组中节点的path的idx元素是否都相等
|
|
||||||
function isEqualByIndex(idx: number, nodes: Array<VNode>) {
|
|
||||||
let val = nodes[0].path[idx];
|
|
||||||
for (let i = 1; i < nodes.length; i++) {
|
|
||||||
let node = nodes[i];
|
|
||||||
if (val !== node.path[idx]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 尝试去渲染,已有任务就跳出
|
|
||||||
export function tryRenderRoot(treeRoot: VNode) {
|
|
||||||
if (treeRoot.shouldUpdate && treeRoot.task === null) {
|
|
||||||
// 任务放进queue,但是调度开始还是异步的
|
|
||||||
treeRoot.task = pushRenderCallback(
|
|
||||||
renderFromRoot.bind(null, treeRoot),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 总体任务入口
|
|
||||||
function renderFromRoot(treeRoot) {
|
|
||||||
runAsyncEffects();
|
|
||||||
|
|
||||||
// 1. 构建vNode树
|
|
||||||
buildVNodeTree(treeRoot);
|
|
||||||
|
|
||||||
// 致命错误直接抛出
|
|
||||||
if (getBuildResult() === BuildFatalErrored) {
|
|
||||||
throw unrecoverableErrorDuringBuild;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 提交变更
|
|
||||||
submitToRender(treeRoot);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为重新进行深度遍历做准备
|
// 为重新进行深度遍历做准备
|
||||||
function resetProcessingVariables(startUpdateVNode: VNode) {
|
function resetProcessingVariables(startUpdateVNode: VNode) {
|
||||||
// 创建processing
|
// 创建processing
|
||||||
|
@ -195,6 +69,71 @@ function resetProcessingVariables(startUpdateVNode: VNode) {
|
||||||
unrecoverableErrorDuringBuild = null;
|
unrecoverableErrorDuringBuild = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================== 向上递归 ==============================
|
||||||
|
|
||||||
|
// 尝试完成当前工作单元,然后移动到下一个兄弟工作单元。如果没有更多的同级,请返回父vNode。
|
||||||
|
function bubbleVNode(vNode: VNode): void {
|
||||||
|
let node = vNode;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const parent = node.parent;
|
||||||
|
|
||||||
|
if (!node.flags.Interrupted) { // vNode没有抛出异常
|
||||||
|
componentRenders[node.tag].bubbleRender(node);
|
||||||
|
|
||||||
|
// 设置node的childShouldUpdate属性
|
||||||
|
updateChildShouldUpdate(node);
|
||||||
|
|
||||||
|
if (parent !== null && node !== getStartVNode() && !parent.flags.Interrupted) {
|
||||||
|
collectDirtyNodes(node, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回到了开始遍历的节点
|
||||||
|
if (node === getStartVNode()) {
|
||||||
|
if (node.tag !== TreeRoot) {
|
||||||
|
// 设置父node的childShouldUpdate属性
|
||||||
|
updateParentsChildShouldUpdate(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
processing = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const siblingVNode = getSiblingVNode(node);
|
||||||
|
if (siblingVNode !== null) { // 有兄弟vNode
|
||||||
|
processing = siblingVNode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 继续遍历parent
|
||||||
|
node = parent;
|
||||||
|
// 更新processing,抛出异常时可以使用
|
||||||
|
processing = node;
|
||||||
|
} while (node !== null);
|
||||||
|
|
||||||
|
// 修改结果
|
||||||
|
if (getBuildResult() === BuildInComplete) {
|
||||||
|
setBuildResult(BuildCompleted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(root, error): void {
|
||||||
|
if (processing === null || processing.parent === null) {
|
||||||
|
// 这是一个致命的错误,因为没有祖先可以处理它
|
||||||
|
setBuildResult(BuildFatalErrored);
|
||||||
|
unrecoverableErrorDuringBuild = error;
|
||||||
|
|
||||||
|
processing = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理capture和bubble阶段抛出的错误
|
||||||
|
handleRenderThrowError(processing, error);
|
||||||
|
|
||||||
|
bubbleVNode(processing);
|
||||||
|
}
|
||||||
|
|
||||||
// ============================== 深度遍历 ==============================
|
// ============================== 深度遍历 ==============================
|
||||||
function buildVNodeTree(treeRoot: VNode) {
|
function buildVNodeTree(treeRoot: VNode) {
|
||||||
const preMode = copyExecuteMode();
|
const preMode = copyExecuteMode();
|
||||||
|
@ -251,20 +190,130 @@ function buildVNodeTree(treeRoot: VNode) {
|
||||||
setExecuteMode(preMode);
|
setExecuteMode(preMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleError(root, error): void {
|
// 总体任务入口
|
||||||
if (processing === null || processing.parent === null) {
|
function renderFromRoot(treeRoot) {
|
||||||
// 这是一个致命的错误,因为没有祖先可以处理它
|
runAsyncEffects();
|
||||||
setBuildResult(BuildFatalErrored);
|
|
||||||
unrecoverableErrorDuringBuild = error;
|
|
||||||
|
|
||||||
processing = null;
|
// 1. 构建vNode树
|
||||||
return;
|
buildVNodeTree(treeRoot);
|
||||||
|
|
||||||
|
// 致命错误直接抛出
|
||||||
|
if (getBuildResult() === BuildFatalErrored) {
|
||||||
|
throw unrecoverableErrorDuringBuild;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理capture和bubble阶段抛出的错误
|
// 2. 提交变更
|
||||||
handleRenderThrowError(processing, error);
|
submitToRender(treeRoot);
|
||||||
|
|
||||||
bubbleVNode(processing);
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试去渲染,已有任务就跳出
|
||||||
|
export function tryRenderRoot(treeRoot: VNode) {
|
||||||
|
if (treeRoot.shouldUpdate && treeRoot.task === null) {
|
||||||
|
// 任务放进queue,但是调度开始还是异步的
|
||||||
|
treeRoot.task = pushRenderCallback(
|
||||||
|
renderFromRoot.bind(null, treeRoot),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发起更新
|
||||||
|
export function launchUpdateFromVNode(vNode: VNode): null | void {
|
||||||
|
// 检查循环调用
|
||||||
|
checkLoopingUpdateLimit();
|
||||||
|
|
||||||
|
// 从当前vNode向上遍历到根节点,修改vNode.shouldUpdate和parent.childShouldUpdate
|
||||||
|
const treeRoot = updateShouldUpdateOfTree(vNode);
|
||||||
|
if (treeRoot === null) {
|
||||||
|
// 可能场景是:the componentWillUnmount method 或 useEffect cleanup function 方法中写异步任务,并且修改state。
|
||||||
|
// 因为异步回调的时候root都可能被清除了。
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存待刷新的节点
|
||||||
|
treeRoot.toUpdateNodes.add(vNode);
|
||||||
|
|
||||||
|
if (checkMode(BySync) && // 非批量
|
||||||
|
!checkMode(InRender)) { // 不是渲染阶段触发
|
||||||
|
|
||||||
|
// 业务直接调用Horizon.render的时候会进入这个分支,同步渲染。
|
||||||
|
// 不能改成下面的异步,否则会有时序问题,因为业务可能会依赖这个渲染的完成。
|
||||||
|
renderFromRoot(treeRoot);
|
||||||
|
} else {
|
||||||
|
tryRenderRoot(treeRoot);
|
||||||
|
|
||||||
|
if (!isExecuting()) {
|
||||||
|
// 同步执行
|
||||||
|
callRenderQueueImmediate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断数组中节点的path的idx元素是否都相等
|
||||||
|
function isEqualByIndex(idx: number, nodes: Array<VNode>) {
|
||||||
|
let val = nodes[0].path[idx];
|
||||||
|
for (let i = 1; i < nodes.length; i++) {
|
||||||
|
let node = nodes[i];
|
||||||
|
if (val !== node.path[idx]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChildByIndex(vNode: VNode, idx: number) {
|
||||||
|
let node = vNode.child;
|
||||||
|
for (let i = 0; i < idx; i++) {
|
||||||
|
node = node.next;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从多个更新节点中,计算出开始节点。即:找到最近的共同的父辈节点
|
||||||
|
export function calcStartUpdateVNode(treeRoot: VNode) {
|
||||||
|
const toUpdateNodes = Array.from(treeRoot.toUpdateNodes);
|
||||||
|
|
||||||
|
if (toUpdateNodes.length === 0) {
|
||||||
|
return treeRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toUpdateNodes.length === 1) {
|
||||||
|
return toUpdateNodes[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 要计算的节点过多,直接返回根节点
|
||||||
|
if (toUpdateNodes.length > 100) {
|
||||||
|
return treeRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找到路径最短的长度
|
||||||
|
let minPath = toUpdateNodes[0].path.length;
|
||||||
|
for (let i = 1; i < toUpdateNodes.length; i++) {
|
||||||
|
let pathLen = toUpdateNodes[i].path.length;
|
||||||
|
if (pathLen < minPath) {
|
||||||
|
minPath = pathLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找出开始不相等的idx
|
||||||
|
let idx = 0;
|
||||||
|
for (; idx < minPath; idx++) {
|
||||||
|
if (!isEqualByIndex(idx, toUpdateNodes)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 得到相等的路径
|
||||||
|
let startNodePath = toUpdateNodes[0].path.slice(0, idx);
|
||||||
|
|
||||||
|
let node = treeRoot;
|
||||||
|
for (let i = 1; i < startNodePath.length; i++) {
|
||||||
|
let pathIndex = startNodePath[i];
|
||||||
|
node = getChildByIndex(node, pathIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setBuildResultError() {
|
export function setBuildResultError() {
|
||||||
|
@ -273,55 +322,6 @@ export function setBuildResultError() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================== 向上递归 ==============================
|
|
||||||
|
|
||||||
// 尝试完成当前工作单元,然后移动到下一个兄弟工作单元。如果没有更多的同级,请返回父vNode。
|
|
||||||
function bubbleVNode(vNode: VNode): void {
|
|
||||||
let node = vNode;
|
|
||||||
|
|
||||||
do {
|
|
||||||
const parent = node.parent;
|
|
||||||
|
|
||||||
if (!node.flags.Interrupted) { // vNode没有抛出异常
|
|
||||||
componentRenders[node.tag].bubbleRender(node);
|
|
||||||
|
|
||||||
// 设置node的childShouldUpdate属性
|
|
||||||
updateChildShouldUpdate(node);
|
|
||||||
|
|
||||||
if (parent !== null && node !== getStartVNode() && !parent.flags.Interrupted) {
|
|
||||||
collectDirtyNodes(node, parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 回到了开始遍历的节点
|
|
||||||
if (node === getStartVNode()) {
|
|
||||||
if (node.tag !== TreeRoot) {
|
|
||||||
// 设置父node的childShouldUpdate属性
|
|
||||||
updateParentsChildShouldUpdate(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
processing = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const siblingVNode = getSiblingVNode(node);
|
|
||||||
if (siblingVNode !== null) { // 有兄弟vNode
|
|
||||||
processing = siblingVNode;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 继续遍历parent
|
|
||||||
node = parent;
|
|
||||||
// 更新processing,抛出异常时可以使用
|
|
||||||
processing = node;
|
|
||||||
} while (node !== null);
|
|
||||||
|
|
||||||
// 修改结果
|
|
||||||
if (getBuildResult() === BuildInComplete) {
|
|
||||||
setBuildResult(BuildCompleted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 收集有变化的节点,在submit阶段继续处理
|
// 收集有变化的节点,在submit阶段继续处理
|
||||||
function collectDirtyNodes(vNode: VNode, parent: VNode): void {
|
function collectDirtyNodes(vNode: VNode, parent: VNode): void {
|
||||||
// 将子树和此vNode的所有效果附加到父树的效果列表中,子项的完成顺序会影响副作用顺序。
|
// 将子树和此vNode的所有效果附加到父树的效果列表中,子项的完成顺序会影响副作用顺序。
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import type {VNode} from './Types';
|
import type { VNode } from './Types';
|
||||||
import {FlagUtils, ShouldCapture} from './vnode/VNodeFlags';
|
import { FlagUtils, ShouldCapture } from './vnode/VNodeFlags';
|
||||||
|
|
||||||
export type Update = {
|
export type Update = {
|
||||||
type: 'Update' | 'Override' | 'ForceUpdate' | 'Error',
|
type: 'Update' | 'Override' | 'ForceUpdate' | 'Error';
|
||||||
content: any,
|
content: any;
|
||||||
callback: Callback | null,
|
callback: Callback | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Callback = () => any;
|
export type Callback = () => any;
|
||||||
|
@ -42,6 +42,18 @@ export function pushUpdate(vNode: VNode, update: Update) {
|
||||||
updates.push(update);
|
updates.push(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCallback(
|
||||||
|
update: Update,
|
||||||
|
inst: any,
|
||||||
|
oldState: any,
|
||||||
|
props: any,): any {
|
||||||
|
const content = update.content;
|
||||||
|
const newState = typeof content === 'function' ? content.call(inst, oldState, props) : content;
|
||||||
|
return (newState === null || newState === undefined)
|
||||||
|
? oldState
|
||||||
|
: { ...oldState, ...newState };
|
||||||
|
}
|
||||||
|
|
||||||
// 根据update获取新的state
|
// 根据update获取新的state
|
||||||
function calcState(
|
function calcState(
|
||||||
vNode: VNode,
|
vNode: VNode,
|
||||||
|
@ -50,24 +62,22 @@ function calcState(
|
||||||
oldState: any,
|
oldState: any,
|
||||||
props: any,
|
props: any,
|
||||||
): any {
|
): any {
|
||||||
if (update.type === UpdateState.Override) {
|
switch (update.type) {
|
||||||
|
case UpdateState.Override:
|
||||||
const content = update.content;
|
const content = update.content;
|
||||||
return typeof content === 'function' ? content.call(inst, oldState, props) : content;
|
return typeof content === 'function' ? content.call(inst, oldState, props) : content;
|
||||||
} else if (update.type === UpdateState.ForceUpdate) {
|
case UpdateState.ForceUpdate:
|
||||||
vNode.isForceUpdate = true;
|
vNode.isForceUpdate = true;
|
||||||
return oldState;
|
return oldState;
|
||||||
} else if (update.type === UpdateState.Error || update.type === UpdateState.Update) {
|
case UpdateState.Error:
|
||||||
if (update.type === UpdateState.Error) {
|
|
||||||
FlagUtils.removeFlag(vNode, ShouldCapture);
|
FlagUtils.removeFlag(vNode, ShouldCapture);
|
||||||
FlagUtils.markDidCapture(vNode);
|
FlagUtils.markDidCapture(vNode);
|
||||||
}
|
return getCallback(update, inst, oldState, props);
|
||||||
const content = update.content;
|
case UpdateState.Update:
|
||||||
const newState = typeof content === 'function' ? content.call(inst, oldState, props) : content;
|
return getCallback(update, inst, oldState, props);
|
||||||
return (newState === null || newState === undefined)
|
default:
|
||||||
? oldState
|
|
||||||
: {...oldState, ...newState}
|
|
||||||
}
|
|
||||||
return oldState;
|
return oldState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收集callback
|
// 收集callback
|
||||||
|
|
|
@ -26,7 +26,7 @@ export class VNode {
|
||||||
suspensePromises: any = null; // suspense组件的promise列表
|
suspensePromises: any = null; // suspense组件的promise列表
|
||||||
changeList: any = null; // DOM的变更列表
|
changeList: any = null; // DOM的变更列表
|
||||||
effectList: any[] = []; // useEffect 的更新数组
|
effectList: any[] = []; // useEffect 的更新数组
|
||||||
updates: any[] = null; // TreeRoot和ClassComponent使用的更新数组
|
updates: any[] | null = null; // TreeRoot和ClassComponent使用的更新数组
|
||||||
stateCallbacks: any[] = []; // 存放存在setState的第二个参数和HorizonDOM.render的第三个参数所在的node数组
|
stateCallbacks: any[] = []; // 存放存在setState的第二个参数和HorizonDOM.render的第三个参数所在的node数组
|
||||||
isForceUpdate: boolean = false; // 是否使用强制更新
|
isForceUpdate: boolean = false; // 是否使用强制更新
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue