diff --git a/libs/horizon/src/dom/DOMOperator.ts b/libs/horizon/src/dom/DOMOperator.ts index bb061fa7..073456fc 100644 --- a/libs/horizon/src/dom/DOMOperator.ts +++ b/libs/horizon/src/dom/DOMOperator.ts @@ -19,7 +19,7 @@ import { } from './valueHandler'; import { compareProps, - setDomProps, updateDomProps + setDomProps, } from './DOMPropertiesHandler/DOMPropertiesHandler'; import { isNativeElement, validateProps } from './validators/ValidateProps'; import { watchValueChange } from './valueHandler/ValueChangeHandler'; @@ -91,7 +91,8 @@ export function initDomProps(dom: Element, tagName: string, rawProps: Props): bo const props: Object = getPropsWithoutValue(tagName, dom, rawProps); // 初始化DOM属性(不包括value,defaultValue) - setDomProps(tagName, dom, props); + const isNativeTag = isNativeElement(tagName, props); + setDomProps(dom, props, isNativeTag, true); if (tagName === 'input' || tagName === 'textarea') { // 增加监听value和checked的set、get方法 @@ -110,7 +111,7 @@ export function getPropChangeList( type: string, lastRawProps: Props, nextRawProps: Props, -): Map { +): Object { // 校验两个对象的不同 validateProps(type, nextRawProps); @@ -118,8 +119,7 @@ export function getPropChangeList( const oldProps: Object = getPropsWithoutValue(type, dom, lastRawProps); const newProps: Object = getPropsWithoutValue(type, dom, nextRawProps); - const changeList = compareProps(oldProps, newProps); - return changeList; + return compareProps(oldProps, newProps); } export function isTextChild(type: string, props: Props): boolean { @@ -168,7 +168,7 @@ export function submitDomUpdate(tag: string, vNode: VNode) { updateCommonProp(element, 'checked', newProps.checked, true); } const isNativeTag = isNativeElement(type, newProps); - updateDomProps(element, changeList, isNativeTag); + setDomProps(element, changeList, isNativeTag, false); updateValue(type, element, newProps); } } diff --git a/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts b/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts index 496d0c2c..c7f76f2f 100644 --- a/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts +++ b/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts @@ -6,37 +6,15 @@ import { setStyles } from './StyleHandler'; import { listenNonDelegatedEvent } from '../../event/EventBinding'; -import { isEventProp, isNativeElement } from '../validators/ValidateProps'; +import { isEventProp } from '../validators/ValidateProps'; -function updateOneProp(dom, propName, isNativeTag, propVal?, isInit?: boolean) { - if (propName === 'style') { - setStyles(dom, propVal); - } else if (isEventProp(propName)) { - // 事件监听属性处理 - if (!allDelegatedHorizonEvents.has(propName)) { - listenNonDelegatedEvent(propName, dom, propVal); - } - } else if (propName === 'children') { // 只处理纯文本子节点,其他children在VNode树中处理 - const type = typeof propVal; - if (type === 'string' || type === 'number') { - dom.textContent = propVal; - } - } else if (propName === 'dangerouslySetInnerHTML') { - dom.innerHTML = propVal.__html; - } else { - if (!isInit || (isInit && propVal != null)) { - updateCommonProp(dom, propName, propVal, isNativeTag); - } - } -} - -// 初始化DOM属性 +// 初始化DOM属性和更新 DOM 属性 export function setDomProps( - tagName: string, dom: Element, props: Object, + isNativeTag: boolean, + isInit: boolean, ): void { - const isNativeTag = isNativeElement(tagName, props); const keysOfProps = Object.keys(props); let propName; let propVal; @@ -45,18 +23,23 @@ export function setDomProps( propName = keysOfProps[i]; propVal = props[propName]; - updateOneProp(dom, propName, isNativeTag, propVal, true); - } -} - -// 更新 DOM 属性 -export function updateDomProps( - dom: Element, - changeList: Map, - isNativeTag: boolean, -): void { - for(const [propName, propVal] of changeList) { - updateOneProp(dom, propName, isNativeTag, propVal); + if (propName === 'style') { + setStyles(dom, propVal); + } else if (isEventProp(propName)) { + // 事件监听属性处理 + if (!allDelegatedHorizonEvents.has(propName)) { + listenNonDelegatedEvent(propName, dom, propVal); + } + } else if (propName === 'children') { // 只处理纯文本子节点,其他children在VNode树中处理 + const type = typeof propVal; + if (type === 'string' || type === 'number') { + dom.textContent = propVal; + } + } else if (propName === 'dangerouslySetInnerHTML') { + dom.innerHTML = propVal.__html; + } else if (!isInit || (isInit && propVal != null)) { + updateCommonProp(dom, propName, propVal, isNativeTag); + } } } @@ -64,9 +47,9 @@ export function updateDomProps( export function compareProps( oldProps: Object, newProps: Object, -): Map { +): Object { let updatesForStyle = {}; - const toUpdateProps = new Map(); + const toUpdateProps = {}; const keysOfOldProps = Object.keys(oldProps); const keysOfNewProps = Object.keys(newProps); @@ -98,11 +81,11 @@ export function compareProps( continue; } else if (isEventProp(propName)) { if (!allDelegatedHorizonEvents.has(propName)) { - toUpdateProps.set(propName, null); + toUpdateProps[propName] = null; } } else { // 其它属性都要加入到删除队列里面,等待删除 - toUpdateProps.set(propName, null); + toUpdateProps[propName] = null; } } @@ -144,7 +127,7 @@ export function compareProps( } } else { // 之前未设置 style 属性或者设置了空值 if (Object.keys(updatesForStyle).length === 0) { - toUpdateProps.set(propName, null); + toUpdateProps[propName] = null; } updatesForStyle = newPropValue; } @@ -153,25 +136,25 @@ export function compareProps( oldHTML = oldPropValue ? oldPropValue.__html : undefined; if (newHTML != null) { if (oldHTML !== newHTML) { - toUpdateProps.set(propName, newPropValue); + toUpdateProps[propName] = newPropValue; } } } else if (propName === 'children') { if (typeof newPropValue === 'string' || typeof newPropValue === 'number') { - toUpdateProps.set(propName, String(newPropValue)); + toUpdateProps[propName] = String(newPropValue); } } else if (isEventProp(propName)) { if (!allDelegatedHorizonEvents.has(propName)) { - toUpdateProps.set(propName, newPropValue); + toUpdateProps[propName] = newPropValue; } } else { - toUpdateProps.set(propName, newPropValue); + toUpdateProps[propName] = newPropValue; } } // 处理style if (Object.keys(updatesForStyle).length > 0) { - toUpdateProps.set('style', updatesForStyle); + toUpdateProps['style'] = updatesForStyle; } return toUpdateProps; diff --git a/libs/horizon/src/event/HorizonEventMain.ts b/libs/horizon/src/event/HorizonEventMain.ts index c550fdbe..08e9f5d0 100644 --- a/libs/horizon/src/event/HorizonEventMain.ts +++ b/libs/horizon/src/event/HorizonEventMain.ts @@ -10,7 +10,7 @@ import { import { getListeners as getChangeListeners } from './simulatedEvtHandler/ChangeEventHandler'; import { getListeners as getSelectionListeners } from './simulatedEvtHandler/SelectionEventHandler'; import { - addOnPrefix, setPropertyWritable, + setPropertyWritable, } from './utils'; import { decorateNativeEvent } from './customEvents/EventFactory'; import { getListenersFromTree } from './ListenerGetter'; @@ -27,7 +27,9 @@ function getCommonListeners( target: null | EventTarget, isCapture: boolean, ): ListenerUnitList { - const horizonEvtName = addOnPrefix(CommonEventToHorizonMap[nativeEvtName]); + const name = CommonEventToHorizonMap[nativeEvtName]; + const horizonEvtName = !name ? '' : `on${name[0].toUpperCase()}${name.slice(1)}`; // 例:dragEnd -> onDragEnd + if (!horizonEvtName) { return []; } diff --git a/libs/horizon/src/event/utils.ts b/libs/horizon/src/event/utils.ts index d4b6f143..09d1b240 100644 --- a/libs/horizon/src/event/utils.ts +++ b/libs/horizon/src/event/utils.ts @@ -6,15 +6,6 @@ export function isInputElement(dom?: HTMLElement): boolean { return false; } - -// 例:dragEnd -> onDragEnd -export function addOnPrefix(name) { - if (!name) { - return ''; - } - return 'on' + name[0].toUpperCase() + name.slice(1); -} - export function setPropertyWritable(obj, propName) { const desc = Object.getOwnPropertyDescriptor(obj, propName); if (!desc || !desc.writable) { diff --git a/libs/horizon/src/renderer/TreeBuilder.ts b/libs/horizon/src/renderer/TreeBuilder.ts index 76de8ae4..7eca2c59 100644 --- a/libs/horizon/src/renderer/TreeBuilder.ts +++ b/libs/horizon/src/renderer/TreeBuilder.ts @@ -59,11 +59,11 @@ function collectDirtyNodes(vNode: VNode, parent: VNode): void { const dirtyNodes = vNode.dirtyNodes; if (dirtyNodes !== null && dirtyNodes.length) { if (parent.dirtyNodes === null) { - parent.dirtyNodes = [...vNode.dirtyNodes]; + parent.dirtyNodes = dirtyNodes; } else { parent.dirtyNodes.push(...vNode.dirtyNodes); + dirtyNodes.length = 0; } - dirtyNodes.length = 0; vNode.dirtyNodes = null; } @@ -236,7 +236,7 @@ function buildVNodeTree(treeRoot: VNode) { // 当在componentWillUnmount中调用setState,parent可能是null,因为startVNode会被clear if (parent !== null) { resetNamespaceCtx(parent); - setNamespaceCtx(parent, parent.outerDom); + setNamespaceCtx(parent, parent.realNode); } // 恢复父节点的context diff --git a/libs/horizon/src/renderer/Types.ts b/libs/horizon/src/renderer/Types.ts index 9acbc42c..f95c4720 100644 --- a/libs/horizon/src/renderer/Types.ts +++ b/libs/horizon/src/renderer/Types.ts @@ -39,7 +39,7 @@ export type ContextType = { export type PortalType = { vtype: number; key: null | string; - outerDom: any; + realNode: any; children: any; }; diff --git a/libs/horizon/src/renderer/UpdateHandler.ts b/libs/horizon/src/renderer/UpdateHandler.ts index a2b55485..e50d1e21 100644 --- a/libs/horizon/src/renderer/UpdateHandler.ts +++ b/libs/horizon/src/renderer/UpdateHandler.ts @@ -18,11 +18,6 @@ export enum UpdateState { Error = 'Error', } -// 初始化更新数组 -export function createUpdateArray(vNode: VNode): void { - vNode.updates = []; // 新产生的update会加入这个数组 -} - // 创建update对象 export function newUpdate(): Update { return { @@ -35,8 +30,11 @@ export function newUpdate(): Update { // 将update对象加入updates export function pushUpdate(vNode: VNode, update: Update) { const updates = vNode.updates; - - updates?.push(update); + if (updates !== null) { + updates.push(update); + } else { + vNode.updates = [update]; + } } // 根据update获取新的state @@ -98,12 +96,14 @@ export function processUpdates(vNode: VNode, inst: any, props: any): void { const updates: Updates = vNode.updates; vNode.isForceUpdate = false; - const toProcessUpdates = [...updates]; - updates.length = 0; - - if (toProcessUpdates.length) { - calcUpdates(vNode, props, inst, toProcessUpdates); + if (updates !== null) { + const toProcessUpdates = [...updates]; + updates.length = 0; + if (toProcessUpdates.length) { + calcUpdates(vNode, props, inst, toProcessUpdates); + } } + } export function pushForceUpdate(vNode: VNode) { diff --git a/libs/horizon/src/renderer/components/CreatePortal.ts b/libs/horizon/src/renderer/components/CreatePortal.ts index 38d30ca8..9e5e6a65 100644 --- a/libs/horizon/src/renderer/components/CreatePortal.ts +++ b/libs/horizon/src/renderer/components/CreatePortal.ts @@ -3,13 +3,13 @@ import type {PortalType} from '../Types'; export function createPortal( children: any, - outerDom: any, + realNode: any, key: string = '', ): PortalType { return { vtype: TYPE_PORTAL, key: key == '' ? '' : '' + key, children, - outerDom, + realNode, }; } diff --git a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts index d3033570..f5cb03f9 100644 --- a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts +++ b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts @@ -153,7 +153,7 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) { } break; } else if (newChild.vtype === TYPE_PORTAL) { - if (oldNode === null || oldNode.tag !== DomPortal || oldNode.outerDom !== newChild.outerDom) { + if (oldNode === null || oldNode.tag !== DomPortal || oldNode.realNode !== newChild.realNode) { resultNode = createPortalVNode(newChild); } else { resultNode = updateVNode(oldNode, newChild.children || []); @@ -578,7 +578,7 @@ function diffObjectNodeHandler( } else if (newChild.vtype === TYPE_PORTAL) { if (canReuseNode) { // 可以复用 - if (canReuseNode.tag === DomPortal && canReuseNode.outerDom === newChild.outerDom) { + if (canReuseNode.tag === DomPortal && canReuseNode.realNode === newChild.realNode) { resultNode = updateVNode(canReuseNode, newChild.children || []); startDelVNode = canReuseNode.next; resultNode.next = null; diff --git a/libs/horizon/src/renderer/render/BaseComponent.ts b/libs/horizon/src/renderer/render/BaseComponent.ts index afedf488..c94d815d 100644 --- a/libs/horizon/src/renderer/render/BaseComponent.ts +++ b/libs/horizon/src/renderer/render/BaseComponent.ts @@ -18,7 +18,7 @@ import componentRenders from './index'; function handlerContext(processing: VNode) { switch (processing.tag) { case TreeRoot: - setNamespaceCtx(processing, processing.outerDom); + setNamespaceCtx(processing, processing.realNode); break; case DomComponent: setNamespaceCtx(processing); @@ -29,7 +29,7 @@ function handlerContext(processing: VNode) { break; } case DomPortal: - setNamespaceCtx(processing, processing.outerDom); + setNamespaceCtx(processing, processing.realNode); break; case ContextProvider: { const newValue = processing.props.value; diff --git a/libs/horizon/src/renderer/render/ClassComponent.ts b/libs/horizon/src/renderer/render/ClassComponent.ts index 261fea3f..6db4dcf2 100644 --- a/libs/horizon/src/renderer/render/ClassComponent.ts +++ b/libs/horizon/src/renderer/render/ClassComponent.ts @@ -23,7 +23,6 @@ import { import { FlagUtils, DidCapture } from '../vnode/VNodeFlags'; import { markRef } from './BaseComponent'; import { - createUpdateArray, processUpdates, } from '../UpdateHandler'; import { getContextChangeCtx, setContextChangeCtx } from '../ContextSaver'; @@ -47,15 +46,13 @@ function mountInstance(clazz, processing: VNode, nextProps: object) { } // 构造实例 - callConstructor(processing, clazz, nextProps); + const inst = callConstructor(processing, clazz, nextProps); - const inst = processing.realNode; inst.props = nextProps; inst.state = processing.state; inst.context = getCurrentContext(clazz, processing); inst.refs = {}; - createUpdateArray(processing); processUpdates(processing, inst, nextProps); inst.state = processing.state; @@ -106,7 +103,15 @@ function markLifeCycle(processing: VNode, nextProps: object, shouldUpdate: Boole } // 用于类组件 -export function captureClassComponent(processing: VNode, clazz: any, nextProps: object): VNode | null { +export function captureRender(processing: VNode): VNode | null { + let clazz = processing.type; + let nextProps = processing.props; + if (processing.isLazyComponent) { + nextProps = mergeDefaultProps(clazz, nextProps); + if (processing.promiseResolve) { // 该函数被 lazy 组件使用,未加载的组件需要加载组件的真实内容 + clazz = clazz._load(clazz._content); + } + } const isOldCxtExist = isOldProvider(clazz); cacheOldCtx(processing, isOldCxtExist); @@ -123,18 +128,13 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps: const newContext = getCurrentContext(clazz, processing); // 子节点抛出异常时,如果本class是个捕获异常的处理节点,这时候oldProps是null,所以需要使用props - let oldProps = (processing.flags & DidCapture) === DidCapture ? processing.props : processing.oldProps; - if (processing.isLazyComponent) { - oldProps = mergeDefaultProps(processing.type, oldProps); - } - inst.props = oldProps; + const oldProps = (processing.flags & DidCapture) === DidCapture ? processing.props : processing.oldProps; if (oldProps !== processing.props || inst.context !== newContext) { // 在已挂载的组件接收新的 props 之前被调用 callComponentWillReceiveProps(inst, nextProps, newContext); } - inst.state = processing.state; processUpdates(processing, inst, nextProps); // 如果 props, state, context 都没有变化且 isForceUpdate 为 false则不需要更新 @@ -183,13 +183,6 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps: } } -export function captureRender(processing: VNode): VNode | null { - const clazz = processing.type; - const props = processing.props; - const nextProps = processing.isLazyComponent ? mergeDefaultProps(clazz, props) : props; - return captureClassComponent(processing, clazz, nextProps); -} - export function bubbleRender(processing: VNode) { if (isOldProvider(processing.type)) { resetOldCtx(processing); diff --git a/libs/horizon/src/renderer/render/DomComponent.ts b/libs/horizon/src/renderer/render/DomComponent.ts index ace8f10f..5e8e5164 100644 --- a/libs/horizon/src/renderer/render/DomComponent.ts +++ b/libs/horizon/src/renderer/render/DomComponent.ts @@ -38,14 +38,15 @@ function updateDom( oldProps, newProps, ); - processing.changeList = changeList; // 输入类型的直接标记更新 if (type === 'input' || type === 'textarea' || type === 'select' || type === 'option') { FlagUtils.markUpdate(processing); + processing.changeList = changeList; } else { // 其它的类型,数据有变化才标记更新 - if (changeList.size) { + if (Object.keys(changeList).length) { + processing.changeList = changeList; FlagUtils.markUpdate(processing); } } @@ -105,7 +106,7 @@ export function bubbleRender(processing: VNode) { } } -function captureDomComponent(processing: VNode): VNode | null { +export function captureRender(processing: VNode): VNode | null { setNamespaceCtx(processing); const type = processing.type; @@ -127,7 +128,3 @@ function captureDomComponent(processing: VNode): VNode | null { processing.child = createChildrenByDiff(processing, processing.child, nextChildren, !processing.isCreated); return processing.child; } - -export function captureRender(processing: VNode): VNode | null { - return captureDomComponent(processing); -} diff --git a/libs/horizon/src/renderer/render/DomPortal.ts b/libs/horizon/src/renderer/render/DomPortal.ts index d3f79e58..baf4b500 100644 --- a/libs/horizon/src/renderer/render/DomPortal.ts +++ b/libs/horizon/src/renderer/render/DomPortal.ts @@ -7,12 +7,12 @@ export function bubbleRender(processing: VNode) { resetNamespaceCtx(processing); if (processing.isCreated) { - prePortal(processing.outerDom); + prePortal(processing.realNode); } } function capturePortalComponent(processing: VNode) { - setNamespaceCtx(processing, processing.outerDom); + setNamespaceCtx(processing, processing.realNode); const newElements = processing.props; if (processing.isCreated) { diff --git a/libs/horizon/src/renderer/render/LazyComponent.ts b/libs/horizon/src/renderer/render/LazyComponent.ts index a1f911ad..7f81ab2a 100644 --- a/libs/horizon/src/renderer/render/LazyComponent.ts +++ b/libs/horizon/src/renderer/render/LazyComponent.ts @@ -10,7 +10,7 @@ import { } from '../vnode/VNodeTags'; import { throwIfTrue } from '../utils/throwIfTrue'; import { captureFunctionComponent } from './FunctionComponent'; -import { captureClassComponent } from './ClassComponent'; +import { captureRender as captureClassComponent } from './ClassComponent'; import { captureMemoComponent } from './MemoComponent'; export function bubbleRender() { } diff --git a/libs/horizon/src/renderer/render/TreeRoot.ts b/libs/horizon/src/renderer/render/TreeRoot.ts index 9b5eaa86..33a28402 100644 --- a/libs/horizon/src/renderer/render/TreeRoot.ts +++ b/libs/horizon/src/renderer/render/TreeRoot.ts @@ -12,7 +12,7 @@ export function bubbleRender(processing: VNode) { } function updateTreeRoot(processing) { - setNamespaceCtx(processing, processing.outerDom); + setNamespaceCtx(processing, processing.realNode); const updates = processing.updates; throwIfTrue( diff --git a/libs/horizon/src/renderer/render/class/ClassLifeCycleProcessor.ts b/libs/horizon/src/renderer/render/class/ClassLifeCycleProcessor.ts index 90f662c3..153094e0 100644 --- a/libs/horizon/src/renderer/render/class/ClassLifeCycleProcessor.ts +++ b/libs/horizon/src/renderer/render/class/ClassLifeCycleProcessor.ts @@ -118,15 +118,19 @@ export function callComponentWillUpdate(inst, newProps, newState, nextContext) { } export function callComponentWillReceiveProps(inst, newProps: object, newContext: object) { - const oldState = inst.state; if (inst.componentWillReceiveProps) { + const oldState = inst.state; inst.componentWillReceiveProps(newProps, newContext); + if (inst.state !== oldState) { + changeStateContent.call(inst, UpdateState.Override, inst.state, null); + } } if (inst.UNSAFE_componentWillReceiveProps) { + const oldState = inst.state; inst.UNSAFE_componentWillReceiveProps(newProps, newContext); - } - if (inst.state !== oldState) { - changeStateContent.call(inst, UpdateState.Override, inst.state, null); + if (inst.state !== oldState) { + changeStateContent.call(inst, UpdateState.Override, inst.state, null); + } } } diff --git a/libs/horizon/src/renderer/submit/LifeCycleHandler.ts b/libs/horizon/src/renderer/submit/LifeCycleHandler.ts index 5d8d649a..adb21135 100644 --- a/libs/horizon/src/renderer/submit/LifeCycleHandler.ts +++ b/libs/horizon/src/renderer/submit/LifeCycleHandler.ts @@ -225,12 +225,9 @@ function submitAddition(vNode: VNode): void { let tag; while (parent !== null) { tag = parent.tag; - if (tag === DomComponent) { + if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) { parentDom = parent.realNode; break; - } else if (tag === TreeRoot || tag === DomPortal) { - parentDom = parent.outerDom; - break; } parent = parent.parent; } @@ -292,12 +289,9 @@ function unmountDomComponents(vNode: VNode): void { let tag; while (parent !== null) { tag = parent.tag; - if (tag === DomComponent) { + if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) { currentParent = parent.realNode; break; - } else if (tag === TreeRoot || tag === DomPortal) { - currentParent = parent.outerDom; - break; } parent = parent.parent; } @@ -312,7 +306,7 @@ function unmountDomComponents(vNode: VNode): void { removeChildDom(currentParent, node.realNode); } else if (node.tag === DomPortal) { if (node.child !== null) { - currentParent = node.outerDom; + currentParent = node.realNode; } } else { unmountVNode(node); @@ -349,12 +343,9 @@ function submitClear(vNode: VNode): void { let tag; while (parent !== null) { tag = parent.tag; - if (tag === DomComponent) { + if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) { parentDom = parent.realNode; break; - } else if (tag === TreeRoot || tag === DomPortal) { - parentDom = parent.outerDom; - break; } parent = parent.parent; } diff --git a/libs/horizon/src/renderer/vnode/VNode.ts b/libs/horizon/src/renderer/vnode/VNode.ts index a48c4ab9..b076a3eb 100644 --- a/libs/horizon/src/renderer/vnode/VNode.ts +++ b/libs/horizon/src/renderer/vnode/VNode.ts @@ -39,7 +39,6 @@ export class VNode { dirtyNodes: Array | null = null; // 需要改动的节点数组 shouldUpdate: boolean = false; childShouldUpdate: boolean = false; - outerDom: any; task: any; // 使用这个变量来记录修改前的值,用于恢复。 @@ -67,7 +66,7 @@ export class VNode { belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用 - constructor(tag: VNodeTag, props: any, key: null | string, outerDom) { + constructor(tag: VNodeTag, props: any, key: null | string, realNode) { this.tag = tag; // 对应组件的类型,比如ClassComponent等 this.key = key; @@ -75,10 +74,9 @@ export class VNode { switch (tag) { case TreeRoot: - this.outerDom = outerDom; + this.realNode = realNode; this.task = null; this.toUpdateNodes = new Set(); - this.realNode = null; this.updates = null; this.stateCallbacks = null; this.state = null; @@ -138,6 +136,7 @@ export class VNode { this.stateCallbacks = null; this.isLazyComponent = true; this.lazyType = null; + this.updates = null; break; case Fragment: break; diff --git a/libs/horizon/src/renderer/vnode/VNodeCreator.ts b/libs/horizon/src/renderer/vnode/VNodeCreator.ts index 35b1b354..972a006f 100644 --- a/libs/horizon/src/renderer/vnode/VNodeCreator.ts +++ b/libs/horizon/src/renderer/vnode/VNodeCreator.ts @@ -16,7 +16,6 @@ import { MemoComponent, SuspenseComponent, } from './VNodeTags'; -import { createUpdateArray } from '../UpdateHandler'; import { TYPE_CONTEXT, TYPE_FORWARD_REF, TYPE_FRAGMENT, @@ -39,8 +38,8 @@ const typeMap = { [TYPE_LAZY]: LazyComponent, }; -const newVirtualNode = function(tag: VNodeTag, key?: null | string, vNodeProps?: any, outerDom?: any): VNode { - return new VNode(tag, vNodeProps, key, outerDom); +const newVirtualNode = function(tag: VNodeTag, key?: null | string, vNodeProps?: any, realNode?: any): VNode { + return new VNode(tag, vNodeProps, key, realNode); }; function isClassComponent(comp: Function) { @@ -100,7 +99,7 @@ export function createPortalVNode(portal) { const children = portal.children ?? []; const vNode = newVirtualNode(DomPortal, portal.key, children); vNode.shouldUpdate = true; - vNode.outerDom = portal.outerDom; + vNode.realNode = portal.realNode; return vNode; } @@ -137,7 +136,7 @@ export function createUndeterminedVNode(type, key, props) { export function createTreeRootVNode(container) { const vNode = newVirtualNode(TreeRoot, null, null, container); vNode.path += 0; - createUpdateArray(vNode); + vNode.updates = []; return vNode; } @@ -150,7 +149,7 @@ export function createVNode(tag: VNodeTag | string, ...secondArg) { vNode = newVirtualNode(TreeRoot, null, null, secondArg[0]); vNode.path += 0; - createUpdateArray(vNode); + vNode.updates = []; break; } diff --git a/libs/horizon/src/renderer/vnode/VNodeFlags.ts b/libs/horizon/src/renderer/vnode/VNodeFlags.ts index af0c2fad..91f59d35 100644 --- a/libs/horizon/src/renderer/vnode/VNodeFlags.ts +++ b/libs/horizon/src/renderer/vnode/VNodeFlags.ts @@ -24,12 +24,10 @@ const LifecycleEffectArr = Update | Callback | Ref | Snapshot; export class FlagUtils { static removeFlag(node: VNode, flag: number) { - const flags = node.flags; - node.flags = flags & (~flag); + node.flags &= ~flag; } static removeLifecycleEffectFlags(node) { - const flags = node.flags; - node.flags = flags & (~LifecycleEffectArr); + node.flags &= ~LifecycleEffectArr; } static hasAnyFlag(node: VNode) { // 有标志位 return node.flags !== InitFlag; diff --git a/libs/horizon/src/renderer/vnode/VNodeUtils.ts b/libs/horizon/src/renderer/vnode/VNodeUtils.ts index a6521757..acda0b39 100644 --- a/libs/horizon/src/renderer/vnode/VNodeUtils.ts +++ b/libs/horizon/src/renderer/vnode/VNodeUtils.ts @@ -210,7 +210,7 @@ function isPortalRoot(vNode, targetContainer) { while (topVNode !== null) { const grandTag = topVNode.tag; if (grandTag === TreeRoot || grandTag === DomPortal) { - const topContainer = topVNode.outerDom; + const topContainer = topVNode.realNode; // 如果topContainer是targetContainer,不需要在这里处理 if (isSameContainer(topContainer, targetContainer)) { return true; @@ -229,7 +229,7 @@ export function getExactNode(targetVNode, targetContainer) { let vNode = targetVNode; while (vNode !== null) { if (vNode.tag === TreeRoot || vNode.tag === DomPortal) { - let container = vNode.outerDom; + let container = vNode.realNode; if (isSameContainer(container, targetContainer)) { break; }