Match-id-67235ae4d6663ecaefc73d8cadbd3548c3dd52ab

This commit is contained in:
* 2022-04-01 15:56:42 +08:00 committed by *
commit 6ba8beea86
9 changed files with 48 additions and 117 deletions

View File

@ -1,6 +1,6 @@
/** /**
* context * context
* begin阶段会修改一些全局的值complete阶段会恢复 * capture阶段会修改一些全局的值bubble阶段会恢复
*/ */
import type { VNode, ContextType } from './Types'; import type { VNode, ContextType } from './Types';
@ -11,98 +11,50 @@ import { ContextProvider } from './vnode/VNodeTags';
// 保存的是“http://www.w3.org/1999/xhtml”或“http://www.w3.org/2000/svg” // 保存的是“http://www.w3.org/1999/xhtml”或“http://www.w3.org/2000/svg”
// 用于识别是使用document.createElement()还是使用document.createElementNS()创建DOM // 用于识别是使用document.createElement()还是使用document.createElementNS()创建DOM
const CTX_NAMESPACE = 'CTX_NAMESPACE';
// 保存的是Horizon.createContext()的值或Provider重新设置的值
const CTX_CONTEXT = 'CTX_CONTEXT';
// 旧版context API,是否更改。
const CTX_OLD_CHANGE = 'CTX_OLD_CHANGE';
let ctxOldChange = false;
let ctxNamespace = ''; let ctxNamespace = '';
function setContext(vNode: VNode, contextName, value) {
if (vNode.contexts === null) {
vNode.contexts = {
[contextName]: value,
};
} else {
vNode.contexts[contextName] = value;
}
}
function getContext(vNode: VNode, contextName) {
if (vNode.contexts !== null) {
return vNode.contexts[contextName];
}
}
// capture阶段设置 // capture阶段设置
function setNamespaceCtx(vNode: VNode, dom?: Container) { export function setNamespaceCtx(vNode: VNode, dom?: Container) {
const nextContext = getNSCtx(ctxNamespace, vNode.type, dom); const nextContext = getNSCtx(ctxNamespace, vNode.type, dom);
setContext(vNode, CTX_NAMESPACE, ctxNamespace); vNode.context = ctxNamespace;
ctxNamespace = nextContext; ctxNamespace = nextContext;
} }
// bubble阶段恢复 // bubble阶段恢复
function resetNamespaceCtx(vNode: VNode) { export function resetNamespaceCtx(vNode: VNode) {
ctxNamespace = getContext(vNode, CTX_NAMESPACE); ctxNamespace = vNode.context;
} }
function getNamespaceCtx(): string { export function getNamespaceCtx(): string {
return ctxNamespace; return ctxNamespace;
} }
function setContextCtx<T>(providerVNode: VNode, nextValue: T) { export function setContext<T>(providerVNode: VNode, nextValue: T) {
const context: ContextType<T> = providerVNode.type._context; const context: ContextType<T> = providerVNode.type._context;
setContext(providerVNode, CTX_CONTEXT, context.value); providerVNode.context = context.value;
context.value = nextValue; context.value = nextValue;
} }
function resetContextCtx(providerVNode: VNode) { export function resetContext(providerVNode: VNode) {
const context: ContextType<any> = providerVNode.type._context; const context: ContextType<any> = providerVNode.type._context;
context.value = getContext(providerVNode, CTX_CONTEXT); context.value = providerVNode.context;
} }
// 在局部更新时恢复父节点的context // 在局部更新时恢复父节点的context
function recoverParentsContextCtx(vNode: VNode) { export function recoverParentContext(vNode: VNode) {
let parent = vNode.parent; let parent = vNode.parent;
while (parent !== null) { while (parent !== null) {
if (parent.tag === ContextProvider) { if (parent.tag === ContextProvider) {
const newValue = parent.props.value; parent.context = parent.props.value;
setContextCtx(parent, newValue);
} }
parent = parent.parent; parent = parent.parent;
} }
} }
function setContextChangeCtx(providerVNode: VNode, didChange: boolean) {
setContext(providerVNode, CTX_OLD_CHANGE, didChange);
ctxOldChange = didChange;
}
function getContextChangeCtx() {
return ctxOldChange;
}
function resetContextChangeCtx(vNode: VNode) {
ctxOldChange = getContext(vNode, CTX_OLD_CHANGE);
}
export {
getNamespaceCtx,
resetNamespaceCtx,
setNamespaceCtx,
setContextCtx,
resetContextCtx,
recoverParentsContextCtx,
setContextChangeCtx,
getContextChangeCtx,
resetContextChangeCtx,
};

View File

@ -29,7 +29,7 @@ import {
isExecuting, isExecuting,
setExecuteMode setExecuteMode
} from './ExecuteMode'; } from './ExecuteMode';
import { recoverParentsContextCtx, resetNamespaceCtx, setNamespaceCtx } from './ContextSaver'; import { recoverParentContext, resetNamespaceCtx, setNamespaceCtx } from './ContextSaver';
import { import {
updateChildShouldUpdate, updateChildShouldUpdate,
updateParentsChildShouldUpdate, updateParentsChildShouldUpdate,
@ -231,7 +231,7 @@ function buildVNodeTree(treeRoot: VNode) {
} }
// 恢复父节点的context // 恢复父节点的context
recoverParentsContextCtx(startVNode); recoverParentContext(startVNode);
} }
// 重置环境变量,为重新进行深度遍历做准备 // 重置环境变量,为重新进行深度遍历做准备

View File

@ -7,7 +7,7 @@ import {
TreeRoot, TreeRoot,
SuspenseComponent, SuspenseComponent,
} from '../vnode/VNodeTags'; } from '../vnode/VNodeTags';
import { getContextChangeCtx, setContextCtx, setNamespaceCtx } from '../ContextSaver'; 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';
@ -26,7 +26,7 @@ function handlerContext(processing: VNode) {
break; break;
case ContextProvider: { case ContextProvider: {
const newValue = processing.props.value; const newValue = processing.props.value;
setContextCtx(processing, newValue); setContext(processing, newValue);
break; break;
} }
// No Default // No Default
@ -41,7 +41,6 @@ export function captureVNode(processing: VNode): VNode | null {
if ( if (
!processing.isCreated && !processing.isCreated &&
processing.oldProps === processing.props && processing.oldProps === processing.props &&
!getContextChangeCtx() &&
!processing.shouldUpdate !processing.shouldUpdate
) { ) {
// 复用还需对stack进行处理 // 复用还需对stack进行处理

View File

@ -18,7 +18,6 @@ import { markRef } from './BaseComponent';
import { import {
processUpdates, processUpdates,
} from '../UpdateHandler'; } from '../UpdateHandler';
import { getContextChangeCtx } from '../ContextSaver';
import { setProcessingClassVNode } from '../GlobalVar'; import { setProcessingClassVNode } from '../GlobalVar';
import { onlyUpdateChildVNodes } from '../vnode/VNodeCreator'; import { onlyUpdateChildVNodes } from '../vnode/VNodeCreator';
import { createChildrenByDiff } from '../diff/nodeDiffComparator'; import { createChildrenByDiff } from '../diff/nodeDiffComparator';
@ -87,7 +86,7 @@ function callUpdateLifeCycle(processing: VNode, nextProps: object, clazz) {
} }
} }
function markLifeCycle(processing: VNode, nextProps: object, shouldUpdate: Boolean) { function markLifeCycle(processing: VNode, nextProps: object, shouldUpdate: boolean) {
if (processing.isCreated) { if (processing.isCreated) {
markComponentDidMount(processing); markComponentDidMount(processing);
} else if (processing.state !== processing.oldState || shouldUpdate) { } else if (processing.state !== processing.oldState || shouldUpdate) {
@ -136,7 +135,6 @@ export function captureRender(processing: VNode): VNode | null {
// 如果 props, state, context 都没有变化且 isForceUpdate 为 false则不需要更新 // 如果 props, state, context 都没有变化且 isForceUpdate 为 false则不需要更新
shouldUpdate = oldProps !== processing.props || shouldUpdate = oldProps !== processing.props ||
inst.state !== processing.state || inst.state !== processing.state ||
getContextChangeCtx() ||
processing.isForceUpdate; processing.isForceUpdate;
if (shouldUpdate) { if (shouldUpdate) {
@ -172,4 +170,4 @@ export function captureRender(processing: VNode): VNode | null {
} }
} }
export function bubbleRender(processing: VNode) {} export function bubbleRender() {}

View File

@ -4,9 +4,8 @@ import { isSame } from '../utils/compare';
import { ClassComponent, ContextProvider } from '../vnode/VNodeTags'; import { ClassComponent, ContextProvider } from '../vnode/VNodeTags';
import { pushForceUpdate } from '../UpdateHandler'; import { pushForceUpdate } from '../UpdateHandler';
import { import {
getContextChangeCtx, resetContext,
resetContextCtx, setContext,
setContextCtx,
} from '../ContextSaver'; } from '../ContextSaver';
import { travelVNodeTree } from '../vnode/VNodeUtils'; import { travelVNodeTree } from '../vnode/VNodeUtils';
import { launchUpdateFromVNode } from '../TreeBuilder'; import { launchUpdateFromVNode } from '../TreeBuilder';
@ -75,14 +74,14 @@ function captureContextProvider(processing: VNode): VNode | null {
const newCtx = newProps.value; const newCtx = newProps.value;
// 更新processing的context值为newProps.value // 更新processing的context值为newProps.value
setContextCtx(processing, newCtx); setContext(processing, newCtx);
if (oldProps !== null) { if (oldProps !== null) {
const oldCtx = oldProps.value; const oldCtx = oldProps.value;
const isSameContext = isSame(oldCtx, newCtx); const isSameContext = isSame(oldCtx, newCtx);
if (isSameContext) { if (isSameContext) {
// context没有改变复用 // context没有改变复用
if (oldProps.children === newProps.children && !getContextChangeCtx()) { if (oldProps.children === newProps.children) {
return onlyUpdateChildVNodes(processing); return onlyUpdateChildVNodes(processing);
} }
} else { } else {
@ -101,6 +100,6 @@ export function captureRender(processing: VNode): VNode | null {
} }
export function bubbleRender(processing: VNode) { export function bubbleRender(processing: VNode) {
resetContextCtx(processing); resetContext(processing);
} }

View File

@ -1,8 +1,8 @@
import type {VNode} from '../Types'; import type {VNode} from '../Types';
import {captureRender as funCaptureRender} from './FunctionComponent'; import {captureRender as funCaptureRender} from './FunctionComponent';
export function captureRender(processing: VNode, shouldUpdate?: boolean): VNode | null { export function captureRender(processing: VNode): VNode | null {
return funCaptureRender(processing, shouldUpdate); return funCaptureRender(processing);
} }
export function bubbleRender() {} export function bubbleRender() {}

View File

@ -5,7 +5,6 @@ import { resetDepContexts } from '../components/context/Context';
import { runFunctionWithHooks } from '../hooks/HookMain'; import { runFunctionWithHooks } from '../hooks/HookMain';
import { ForwardRef } from '../vnode/VNodeTags'; import { ForwardRef } from '../vnode/VNodeTags';
import { FlagUtils, Update } from '../vnode/VNodeFlags'; import { FlagUtils, Update } from '../vnode/VNodeFlags';
import { getContextChangeCtx } from '../ContextSaver';
import { onlyUpdateChildVNodes } from '../vnode/VNodeCreator'; import { onlyUpdateChildVNodes } from '../vnode/VNodeCreator';
import { createChildrenByDiff } from '../diff/nodeDiffComparator'; import { createChildrenByDiff } from '../diff/nodeDiffComparator';
@ -16,22 +15,10 @@ export function bubbleRender() {
} }
// 判断children是否可以复用 // 判断children是否可以复用
function checkIfCanReuseChildren(processing: VNode, shouldUpdate?: boolean) { function checkIfCanReuseChildren(processing: VNode) {
let isCanReuse = true; return !processing.isCreated &&
processing.oldProps === processing.props &&
if (!processing.isCreated) { !processing.isDepContextChange;
const oldProps = processing.oldProps;
const newProps = processing.props;
// 如果props或者context改变了
if (oldProps !== newProps || getContextChangeCtx() || processing.isDepContextChange) {
isCanReuse = false;
}
} else {
isCanReuse = false;
}
return isCanReuse;
} }
export function setStateChange(isUpdate) { export function setStateChange(isUpdate) {
@ -46,7 +33,6 @@ export function captureFunctionComponent(
processing: VNode, processing: VNode,
funcComp: any, funcComp: any,
nextProps: any, nextProps: any,
shouldUpdate?: boolean,
) { ) {
// 函数组件内已完成异步动作 // 函数组件内已完成异步动作
if (processing.isSuspended) { if (processing.isSuspended) {
@ -58,7 +44,7 @@ export function captureFunctionComponent(
} }
resetDepContexts(processing); resetDepContexts(processing);
const isCanReuse = checkIfCanReuseChildren(processing, shouldUpdate); const isCanReuse = checkIfCanReuseChildren(processing);
// 在执行exeFunctionHook前先设置stateChange为false // 在执行exeFunctionHook前先设置stateChange为false
setStateChange(false); setStateChange(false);
@ -80,7 +66,7 @@ export function captureFunctionComponent(
return processing.child; return processing.child;
} }
export function captureRender(processing: VNode, shouldUpdate?: boolean): VNode | null { export function captureRender(processing: VNode): VNode | null {
const Component = processing.type; const Component = processing.type;
const unresolvedProps = processing.props; const unresolvedProps = processing.props;
const resolvedProps = const resolvedProps =
@ -92,7 +78,6 @@ export function captureRender(processing: VNode, shouldUpdate?: boolean): VNode
processing, processing,
Component, Component,
resolvedProps, resolvedProps,
shouldUpdate,
); );
} }

View File

@ -1,17 +1,16 @@
import type {VNode, PromiseType} from '../Types'; import type { VNode, PromiseType } from '../Types';
import {FlagUtils, Interrupted} from '../vnode/VNodeFlags'; import { FlagUtils, Interrupted } from '../vnode/VNodeFlags';
import {onlyUpdateChildVNodes, updateVNode, createFragmentVNode} from '../vnode/VNodeCreator'; import { onlyUpdateChildVNodes, updateVNode, createFragmentVNode } from '../vnode/VNodeCreator';
import { import {
ClassComponent, ClassComponent,
ForwardRef, ForwardRef,
FunctionComponent, FunctionComponent,
SuspenseComponent, SuspenseComponent,
} from '../vnode/VNodeTags'; } from '../vnode/VNodeTags';
import {pushForceUpdate} from '../UpdateHandler'; import { pushForceUpdate } from '../UpdateHandler';
import {launchUpdateFromVNode, tryRenderFromRoot} from '../TreeBuilder'; import { launchUpdateFromVNode, tryRenderFromRoot } from '../TreeBuilder';
import {updateShouldUpdateOfTree} from '../vnode/VNodeShouldUpdate'; import { updateShouldUpdateOfTree } from '../vnode/VNodeShouldUpdate';
import {getContextChangeCtx} from '../ContextSaver';
import { markVNodePath } from '../utils/vNodePath'; import { markVNodePath } from '../utils/vNodePath';
export enum SuspenseChildStatus { export enum SuspenseChildStatus {
@ -101,7 +100,7 @@ export function captureSuspenseComponent(processing: VNode) {
} }
function updateFallback(processing: VNode): Array<VNode> | VNode | null { function updateFallback(processing: VNode): Array<VNode> | VNode | null {
const childFragment: VNode | null= processing.child; const childFragment: VNode | null = processing.child;
if (childFragment?.childShouldUpdate) { if (childFragment?.childShouldUpdate) {
if (processing.suspenseState.promiseResolved) { if (processing.suspenseState.promiseResolved) {
@ -130,7 +129,6 @@ export function captureRender(processing: VNode, shouldUpdate: boolean): Array<V
if ( if (
!processing.isCreated && !processing.isCreated &&
processing.oldProps === processing.props && processing.oldProps === processing.props &&
!getContextChangeCtx() &&
!shouldUpdate !shouldUpdate
) { ) {
if (processing.suspenseState.childStatus === SuspenseChildStatus.ShowFallback) { if (processing.suspenseState.childStatus === SuspenseChildStatus.ShowFallback) {
@ -178,7 +176,7 @@ export function handleSuspenseChildThrowError(parent: VNode, processing: VNode,
if (processing.tag === ClassComponent) { if (processing.tag === ClassComponent) {
if (processing.isCreated) { if (processing.isCreated) {
// 渲染类组件场景要标志未完成否则会触发componentWillUnmount // 渲染类组件场景要标志未完成否则会触发componentWillUnmount
processing.isSuspended = true ; processing.isSuspended = true;
} else { } else {
// 类组件更新标记强制更新否则被memo等优化跳过 // 类组件更新标记强制更新否则被memo等优化跳过
pushForceUpdate(processing); pushForceUpdate(processing);
@ -187,7 +185,7 @@ export function handleSuspenseChildThrowError(parent: VNode, processing: VNode,
} }
if (processing.tag === FunctionComponent || processing.tag === ForwardRef) { if (processing.tag === FunctionComponent || processing.tag === ForwardRef) {
processing.isSuspended= true; processing.isSuspended = true;
} }
// 应该抛出promise未完成更新标志待更新 // 应该抛出promise未完成更新标志待更新
processing.shouldUpdate = true; processing.shouldUpdate = true;

View File

@ -55,7 +55,7 @@ export class VNode {
task: any; task: any;
// 使用这个变量来记录修改前的值,用于恢复。 // 使用这个变量来记录修改前的值,用于恢复。
contexts: any; context: any;
// 因为LazyComponent会修改tag和type属性为了能识别增加一个属性 // 因为LazyComponent会修改tag和type属性为了能识别增加一个属性
isLazyComponent: boolean; isLazyComponent: boolean;
@ -93,7 +93,7 @@ export class VNode {
this.stateCallbacks = null; this.stateCallbacks = null;
this.state = null; this.state = null;
this.oldState = null; this.oldState = null;
this.contexts = null; this.context = null;
break; break;
case FunctionComponent: case FunctionComponent:
this.realNode = null; this.realNode = null;
@ -112,16 +112,16 @@ export class VNode {
this.depContexts = null; this.depContexts = null;
this.isDepContextChange = false; this.isDepContextChange = false;
this.oldState = null; this.oldState = null;
this.contexts = null; this.context = null;
break; break;
case DomPortal: case DomPortal:
this.realNode = null; this.realNode = null;
this.contexts = null; this.context = null;
break; break;
case DomComponent: case DomComponent:
this.realNode = null; this.realNode = null;
this.changeList = null; this.changeList = null;
this.contexts = null; this.context = null;
break; break;
case DomText: case DomText:
this.realNode = null; this.realNode = null;
@ -137,7 +137,7 @@ export class VNode {
}; };
break; break;
case ContextProvider: case ContextProvider:
this.contexts = null; this.context = null;
break; break;
case MemoComponent: case MemoComponent:
this.effectList = null; this.effectList = null;