diff --git a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts index 773a15fd..c6f509b1 100644 --- a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts +++ b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts @@ -1,5 +1,5 @@ import type { VNode } from '../Types'; -import { FlagUtils } from '../vnode/VNodeFlags'; +import { FlagUtils, DirectAddition } from '../vnode/VNodeFlags'; import { TYPE_COMMON_ELEMENT, TYPE_FRAGMENT, TYPE_PORTAL } from '../../external/JSXElementType'; import { DomText, DomPortal, Fragment, DomComponent } from '../vnode/VNodeTags'; import {updateVNode, createVNodeFromElement, updateVNodePath, createFragmentVNode, createPortalVNode, createDomTextVNode} from '../vnode/VNodeCreator'; @@ -347,11 +347,23 @@ function diffArrayNodesHandler( // 4. 新节点还有一部分,但是老节点已经没有了 if (oldNode === null) { + + let isDirectAdd = false; + // TODO: 是否可以扩大至非dom类型节点 + // 如果dom节点在上次添加前没有节点,说明本次添加时,可以直接添加到最后,不需要通过 getSiblingDom 函数找到 before 节点 + if (parentNode.tag === DomComponent && parentNode.oldProps?.children?.length === 0 && rightIdx - leftIdx === newChildren.length) { + isDirectAdd = true; + } for (; leftIdx < rightIdx; leftIdx++) { newNode = getNewNode(parentNode, newChildren[leftIdx], null); if (newNode !== null) { - theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing); + if (isComparing) { + FlagUtils.setAddition(newNode); + } + if (isDirectAdd) { + FlagUtils.markDirectAddition(newNode); + } newNode.eIndex = leftIdx; appendNode(newNode); } diff --git a/libs/horizon/src/renderer/submit/LifeCycleHandler.ts b/libs/horizon/src/renderer/submit/LifeCycleHandler.ts index 554d7d0f..5d8d649a 100644 --- a/libs/horizon/src/renderer/submit/LifeCycleHandler.ts +++ b/libs/horizon/src/renderer/submit/LifeCycleHandler.ts @@ -17,7 +17,7 @@ import { SuspenseComponent, MemoComponent, } from '../vnode/VNodeTags'; -import { FlagUtils, ResetText, Clear, Update } from '../vnode/VNodeFlags'; +import { FlagUtils, ResetText, Clear, Update, DirectAddition } from '../vnode/VNodeFlags'; import { mergeDefaultProps } from '../render/LazyComponent'; import { submitDomUpdate, @@ -241,6 +241,11 @@ function submitAddition(vNode: VNode): void { FlagUtils.removeFlag(parent, ResetText); } + if ((vNode.flags & DirectAddition) === DirectAddition) { + insertOrAppendPlacementNode(vNode, null, parentDom); + FlagUtils.removeFlag(vNode, DirectAddition); + return; + } const before = getSiblingDom(vNode); insertOrAppendPlacementNode(vNode, before, parentDom); } diff --git a/libs/horizon/src/renderer/vnode/VNodeFlags.ts b/libs/horizon/src/renderer/vnode/VNodeFlags.ts index 62f98803..af0c2fad 100644 --- a/libs/horizon/src/renderer/vnode/VNodeFlags.ts +++ b/libs/horizon/src/renderer/vnode/VNodeFlags.ts @@ -5,20 +5,21 @@ import type { VNode } from '../Types'; -export const InitFlag = /** */ 0b000000000000; +export const InitFlag = /** */ 0; // vNode节点的flags -export const Addition = /** */ 0b100000000000; -export const Update = /** */ 0b010000000000; -export const Deletion = /** */ 0b001000000000; -export const ResetText =/** */ 0b000100000000; -export const Callback = /** */ 0b000010000000; -export const DidCapture =/** */ 0b000001000000; -export const Ref = /** */ 0b000000100000; -export const Snapshot = /** */ 0b000000010000; -export const Interrupted = /** */ 0b000000001000; // 被中断了,抛出错误的vNode以及它的父vNode -export const ShouldCapture =/** */ 0b000000000100; -export const ForceUpdate = /** */ 0b000000000010; // For suspense -export const Clear = /** */ 0b000000000001; +export const DirectAddition = /** */ 1 << 0; // 在本次更新前入股父dom没有子节点,说明本次可以直接添加至父节点,不需要通过 getSiblingDom 找到 before 节点 +export const Addition = /** */ 1 << 1; +export const Update = /** */ 1 << 2; +export const Deletion = /** */ 1 << 3; +export const ResetText =/** */ 1 << 4; +export const Callback = /** */ 1 << 5; +export const DidCapture =/** */ 1 << 6; +export const Ref = /** */ 1 << 7; +export const Snapshot = /** */ 1 << 8; +export const Interrupted = /** */ 1 << 9; // 被中断了,抛出错误的vNode以及它的父vNode +export const ShouldCapture =/** */ 1 << 11; +export const ForceUpdate = /** */ 1 << 12; // For suspense +export const Clear = /** */ 1 << 13; const LifecycleEffectArr = Update | Callback | Ref | Snapshot; export class FlagUtils { @@ -44,6 +45,10 @@ export class FlagUtils { static setAddition(node: VNode) { node.flags = Addition; } + + static markDirectAddition(node: VNode) { + node.flags |= DirectAddition; + } static markUpdate(node: VNode) { node.flags |= Update; } diff --git a/libs/horizon/src/renderer/vnode/VNodeUtils.ts b/libs/horizon/src/renderer/vnode/VNodeUtils.ts index c1b0c1dc..a6521757 100644 --- a/libs/horizon/src/renderer/vnode/VNodeUtils.ts +++ b/libs/horizon/src/renderer/vnode/VNodeUtils.ts @@ -169,7 +169,7 @@ export function getSiblingDom(vNode: VNode): Element | null { // 如果不是dom节点,往下找 while (!isDomVNode(node)) { // 如果节点也是Addition - if ((node.flags & Addition) ===Addition) { + if ((node.flags & Addition) === Addition) { continue findSibling; } @@ -183,7 +183,7 @@ export function getSiblingDom(vNode: VNode): Element | null { } } - if ((node.flags & Addition) ===InitFlag) { + if ((node.flags & Addition) === InitFlag) { // 找到 return node.realNode; }