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 { callRenderQueueImmediate } from './src/renderer/taskExecutor/RenderQueue';
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后面的代码是在刷新完成后才执行。
const act = fun => {

View File

@ -9,6 +9,15 @@ export function setProcessingClassVNode(vNode: VNode | null) {
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;
export function getStartVNode(): VNode | null {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,6 @@ import type { Hook, Reducer, Trigger, Update } from './HookType';
import {
createHook,
getCurrentHook,
getProcessingVNode,
throwNotInFuncError
} from './BaseHook';
import {
@ -12,6 +11,7 @@ import { isSame } from '../utils/compare';
import { setStateChange } from '../render/FunctionComponent';
import { getHookStage, HookStage } from './HookStage';
import type { VNode } from '../Types';
import {getProcessingVNode} from '../GlobalVar';
export function useReducerImpl<S, P, A>(reducer: (S, A) =>
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 {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
import componentRenders from './index';
import {setProcessingVNode} from '../GlobalVar';
// 复用vNode时也需对stack进行处理
function handlerContext(processing: VNode) {
@ -52,7 +53,12 @@ export function captureVNode(processing: VNode): VNode | null {
const shouldUpdate = processing.shouldUpdate;
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) {

View File

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

View File

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

View File

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

View File

@ -78,9 +78,10 @@ export class VNode {
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode处理ref的时候使用
// 状态管理器使用
// 状态管理器HorizonX使用
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) {
this.tag = tag; // 对应组件的类型比如ClassComponent等
@ -107,7 +108,8 @@ export class VNode {
this.isDepContextChange = false;
this.oldHooks = null;
this.isStoreChange = false;
this.functionToObserver = null;
this.observers = null;
this.classComponentWillUnmount = null;
break;
case ClassComponent:
this.realNode = null;
@ -119,6 +121,9 @@ export class VNode {
this.isDepContextChange = false;
this.oldState = null;
this.context = null;
this.isStoreChange = false;
this.observers = null;
this.classComponentWillUnmount = null;
break;
case DomPortal:
this.realNode = null;