Match-id-ad10a00eaf81b70f1722a3baff0e2650461cb498

This commit is contained in:
* 2022-06-08 14:49:05 +08:00 committed by *
commit d45d6629aa
13 changed files with 52 additions and 36 deletions

View File

@ -30,7 +30,7 @@ import {
import { launchUpdateFromVNode as _launchUpdateFromVNode, asyncUpdates } from './src/renderer/TreeBuilder'; import { launchUpdateFromVNode as _launchUpdateFromVNode, asyncUpdates } from './src/renderer/TreeBuilder';
import { callRenderQueueImmediate } from './src/renderer/taskExecutor/RenderQueue'; import { callRenderQueueImmediate } from './src/renderer/taskExecutor/RenderQueue';
import { runAsyncEffects } from './src/renderer/submit/HookEffectHandler'; import { runAsyncEffects } from './src/renderer/submit/HookEffectHandler';
import { getProcessingVNode as _getProcessingVNode } from './src/renderer/hooks/BaseHook'; import { getProcessingVNode as _getProcessingVNode } from './src/renderer/GlobalVar';
// act用于测试作用是如果fun触发了刷新包含了异步刷新可以保证在act后面的代码是在刷新完成后才执行。 // act用于测试作用是如果fun触发了刷新包含了异步刷新可以保证在act后面的代码是在刷新完成后才执行。
const act = fun => { const act = fun => {

View File

@ -9,6 +9,15 @@ export function setProcessingClassVNode(vNode: VNode | null) {
processingClassVNode = vNode; processingClassVNode = vNode;
} }
// capture阶段正在处理的VNode
let processingVNode: VNode | null = null;
export function getProcessingVNode() {
return processingVNode;
}
export function setProcessingVNode(vNode: VNode | null) {
processingVNode = vNode;
}
// 计算出来的刷新节点,不一定是根节点 // 计算出来的刷新节点,不一定是根节点
let startVNode: VNode | null = null; let startVNode: VNode | null = null;
export function getStartVNode(): VNode | null { export function getStartVNode(): VNode | null {

View File

@ -242,26 +242,25 @@ function buildVNodeTree(treeRoot: VNode) {
startVNode.props = startVNode.devProps; startVNode.props = startVNode.devProps;
startVNode.devProps = undefined; startVNode.devProps = undefined;
} }
while (processing !== null) { while (processing !== null) {
try { try {
while (processing !== null) { // 捕获创建 vNodes
// 捕获创建 vNodes const next = captureVNode(processing);
const next = captureVNode(processing);
if (next === null) { if (next === null) {
// 如果没有子节点,那么就完成当前节点,开始冒泡 // 如果没有子节点,那么就完成当前节点,开始冒泡
bubbleVNode(processing); bubbleVNode(processing);
} else { } else {
processing = next; processing = next;
}
} }
setProcessingClassVNode(null);
} catch (thrownValue) { } catch (thrownValue) {
handleError(treeRoot, thrownValue); handleError(treeRoot, thrownValue);
} }
} }
setProcessingClassVNode(null);
setExecuteMode(preMode); setExecuteMode(preMode);
} }

View File

@ -1,7 +1,5 @@
import type { VNode } from '../Types';
import type { Hook } from './HookType'; import type { Hook } from './HookType';
import {getProcessingVNode} from '../GlobalVar';
let processingVNode: VNode | null = null;
// lastTimeHook是上一次执行func时产生的hooks中与currentHook对应的hook // lastTimeHook是上一次执行func时产生的hooks中与currentHook对应的hook
let lastTimeHook: Hook<any, any> | null = null; let lastTimeHook: Hook<any, any> | null = null;
@ -9,14 +7,6 @@ let lastTimeHook: Hook<any, any> | null = null;
// 当前hook函数对应的hook对象 // 当前hook函数对应的hook对象
let currentHook: Hook<any, any> | null = null; let currentHook: Hook<any, any> | null = null;
export function getProcessingVNode() {
return processingVNode;
}
export function setProcessingVNode(vNode: VNode | null) {
processingVNode = vNode;
}
export function getLastTimeHook() { export function getLastTimeHook() {
return lastTimeHook; return lastTimeHook;
} }
@ -37,6 +27,7 @@ export function throwNotInFuncError() {
// 新建一个hook并放到vNode.hooks中 // 新建一个hook并放到vNode.hooks中
export function createHook(state: any = null): Hook<any, any> { export function createHook(state: any = null): Hook<any, any> {
const processingVNode = getProcessingVNode();
const newHook: Hook<any, any> = { const newHook: Hook<any, any> = {
state: state, state: state,
hIndex: processingVNode.hooks.length, hIndex: processingVNode.hooks.length,
@ -56,6 +47,7 @@ export function getNextHook(hook: Hook<any, any>, hooks: Array<Hook<any, any>>)
// processing中的hook和上一次执行中的hook需要同时往前走 // processing中的hook和上一次执行中的hook需要同时往前走
// 原因1.比对hook的数量有没有变化非必要2.从上一次执行中的hook获取removeEffect // 原因1.比对hook的数量有没有变化非必要2.从上一次执行中的hook获取removeEffect
export function getCurrentHook(): Hook<any, any> { export function getCurrentHook(): Hook<any, any> {
const processingVNode = getProcessingVNode();
currentHook = currentHook !== null ? currentHook = currentHook !== null ?
getNextHook(currentHook, processingVNode.hooks) : getNextHook(currentHook, processingVNode.hooks) :
(processingVNode.hooks[0] || null); (processingVNode.hooks[0] || null);

View File

@ -8,7 +8,7 @@ import {useImperativeHandleImpl} from './UseImperativeHook';
import {useReducerImpl} from './UseReducerHook'; import {useReducerImpl} from './UseReducerHook';
import {useStateImpl} from './UseStateHook'; import {useStateImpl} from './UseStateHook';
import {getNewContext} from '../components/context/Context'; import {getNewContext} from '../components/context/Context';
import {getProcessingVNode} from './BaseHook'; import {getProcessingVNode} from '../GlobalVar';
import {Ref, Trigger} from './HookType'; import {Ref, Trigger} from './HookType';
type BasicStateAction<S> = ((S) => S) | S; type BasicStateAction<S> = ((S) => S) | S;

View File

@ -3,7 +3,6 @@ import type {VNode} from '../Types';
import { import {
getLastTimeHook, getLastTimeHook,
setLastTimeHook, setLastTimeHook,
setProcessingVNode,
setCurrentHook, getNextHook setCurrentHook, getNextHook
} from './BaseHook'; } from './BaseHook';
import {HookStage, setHookStage} from './HookStage'; import {HookStage, setHookStage} from './HookStage';
@ -18,8 +17,6 @@ export function runFunctionWithHooks<Props extends Record<string, any>, Arg>(
// 重置全局变量 // 重置全局变量
resetGlobalVariable(); resetGlobalVariable();
setProcessingVNode(processing);
processing.oldHooks = processing.hooks; processing.oldHooks = processing.hooks;
processing.hooks = []; processing.hooks = [];
processing.effectList = []; processing.effectList = [];
@ -52,7 +49,6 @@ export function runFunctionWithHooks<Props extends Record<string, any>, Arg>(
function resetGlobalVariable() { function resetGlobalVariable() {
setHookStage(null); setHookStage(null);
setProcessingVNode(null);
setLastTimeHook(null); setLastTimeHook(null);
setCurrentHook(null); setCurrentHook(null);
} }

View File

@ -2,13 +2,14 @@ import {
createHook, createHook,
getCurrentHook, getCurrentHook,
getLastTimeHook, getLastTimeHook,
getProcessingVNode, throwNotInFuncError throwNotInFuncError
} from './BaseHook'; } from './BaseHook';
import {FlagUtils} from '../vnode/VNodeFlags'; import {FlagUtils} from '../vnode/VNodeFlags';
import {EffectConstant} from './EffectConstant'; import {EffectConstant} from './EffectConstant';
import type {Effect, EffectList} from './HookType'; import type {Effect, EffectList} from './HookType';
import {getHookStage, HookStage} from './HookStage'; import {getHookStage, HookStage} from './HookStage';
import {isArrayEqual} from '../utils/compare'; import {isArrayEqual} from '../utils/compare';
import {getProcessingVNode} from '../GlobalVar';
export function useEffectImpl(effectFunc: () => (() => void) | void, deps?: Array<any> | null,): void { export function useEffectImpl(effectFunc: () => (() => void) | void, deps?: Array<any> | null,): void {
// 异步触发的effect // 异步触发的effect

View File

@ -2,7 +2,6 @@ import type { Hook, Reducer, Trigger, Update } from './HookType';
import { import {
createHook, createHook,
getCurrentHook, getCurrentHook,
getProcessingVNode,
throwNotInFuncError throwNotInFuncError
} from './BaseHook'; } from './BaseHook';
import { import {
@ -12,6 +11,7 @@ import { isSame } from '../utils/compare';
import { setStateChange } from '../render/FunctionComponent'; import { setStateChange } from '../render/FunctionComponent';
import { getHookStage, HookStage } from './HookStage'; import { getHookStage, HookStage } from './HookStage';
import type { VNode } from '../Types'; import type { VNode } from '../Types';
import {getProcessingVNode} from '../GlobalVar';
export function useReducerImpl<S, P, A>(reducer: (S, A) => export function useReducerImpl<S, P, A>(reducer: (S, A) =>
S, initArg: P, init?: (P) => S, isUseState?: boolean): [S, Trigger<A>] | void { S, initArg: P, init?: (P) => S, isUseState?: boolean): [S, Trigger<A>] | void {

View File

@ -11,6 +11,7 @@ import { setContext, setNamespaceCtx } from '../ContextSaver';
import { FlagUtils } from '../vnode/VNodeFlags'; import { FlagUtils } from '../vnode/VNodeFlags';
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator'; import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
import componentRenders from './index'; import componentRenders from './index';
import {setProcessingVNode} from '../GlobalVar';
// 复用vNode时也需对stack进行处理 // 复用vNode时也需对stack进行处理
function handlerContext(processing: VNode) { function handlerContext(processing: VNode) {
@ -52,7 +53,12 @@ export function captureVNode(processing: VNode): VNode | null {
const shouldUpdate = processing.shouldUpdate; const shouldUpdate = processing.shouldUpdate;
processing.shouldUpdate = false; processing.shouldUpdate = false;
return component.captureRender(processing, shouldUpdate);
setProcessingVNode(processing);
const child = component.captureRender(processing, shouldUpdate);
setProcessingVNode(null);
return child;
} }
export function markRef(processing: VNode) { export function markRef(processing: VNode) {

View File

@ -58,6 +58,8 @@ function mountInstance(ctor, processing: VNode, nextProps: object) {
// 构建子节点 // 构建子节点
function createChildren(clazz: any, processing: VNode) { function createChildren(clazz: any, processing: VNode) {
processing.isStoreChange = false;
markRef(processing); markRef(processing);
setProcessingClassVNode(processing); setProcessingClassVNode(processing);
@ -157,7 +159,7 @@ export function captureRender(processing: VNode): VNode | null {
} }
// 如果捕获了 error必须更新 // 如果捕获了 error必须更新
const isCatchError = (processing.flags & DidCapture) === DidCapture; const isCatchError = (processing.flags & DidCapture) === DidCapture;
shouldUpdate = isCatchError || shouldUpdate; shouldUpdate = isCatchError || shouldUpdate || processing.isStoreChange;
// 更新ref // 更新ref
markRef(processing); markRef(processing);

View File

@ -55,7 +55,7 @@ export function captureFunctionComponent(
processing, processing,
); );
// 这里需要判断是否可以复用,因为函数组件比起其他组多了context和stateChange两个因素 // 这里需要判断是否可以复用,因为函数组件比起其他组多了context、stateChange、或者store改变了 三个因素
if (isCanReuse && !isStateChange() && !processing.isStoreChange) { if (isCanReuse && !isStateChange() && !processing.isStoreChange) {
FlagUtils.removeFlag(processing, Update); FlagUtils.removeFlag(processing, Update);

View File

@ -196,6 +196,12 @@ function unmountVNode(vNode: VNode): void {
if (instance && typeof instance.componentWillUnmount === 'function' && !vNode.isSuspended) { if (instance && typeof instance.componentWillUnmount === 'function' && !vNode.isSuspended) {
callComponentWillUnmount(vNode, instance); callComponentWillUnmount(vNode, instance);
} }
// HorizonX会在classComponentWillUnmount中清除对VNode的引入用
if (vNode.classComponentWillUnmount) {
vNode.classComponentWillUnmount(vNode);
vNode.classComponentWillUnmount = null;
}
break; break;
} }
case DomComponent: { case DomComponent: {

View File

@ -78,9 +78,10 @@ export class VNode {
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode处理ref的时候使用 belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode处理ref的时候使用
// 状态管理器使用 // 状态管理器HorizonX使用
isStoreChange: boolean; isStoreChange: boolean;
functionToObserver: FunctionToObserver | null; // 记录这个函数组件依赖哪些Observer observers: Set<any> | null = null; // 记录这个函数组件/类组件依赖哪些Observer
classComponentWillUnmount: Function | null; // HorizonX会在classComponentWillUnmount中清除对VNode的引入用
constructor(tag: VNodeTag, props: any, key: null | string, realNode) { constructor(tag: VNodeTag, props: any, key: null | string, realNode) {
this.tag = tag; // 对应组件的类型比如ClassComponent等 this.tag = tag; // 对应组件的类型比如ClassComponent等
@ -107,7 +108,8 @@ export class VNode {
this.isDepContextChange = false; this.isDepContextChange = false;
this.oldHooks = null; this.oldHooks = null;
this.isStoreChange = false; this.isStoreChange = false;
this.functionToObserver = null; this.observers = null;
this.classComponentWillUnmount = null;
break; break;
case ClassComponent: case ClassComponent:
this.realNode = null; this.realNode = null;
@ -119,6 +121,9 @@ export class VNode {
this.isDepContextChange = false; this.isDepContextChange = false;
this.oldState = null; this.oldState = null;
this.context = null; this.context = null;
this.isStoreChange = false;
this.observers = null;
this.classComponentWillUnmount = null;
break; break;
case DomPortal: case DomPortal:
this.realNode = null; this.realNode = null;