diff --git a/packages/inula/package.json b/packages/inula/package.json index 3ec98d8b..d94b77e9 100644 --- a/packages/inula/package.json +++ b/packages/inula/package.json @@ -4,7 +4,7 @@ "keywords": [ "openinula" ], - "version": "0.0.1", + "version": "0.0.1-beta-reconciler-20231009-2", "homepage": "", "bugs": "", "license": "MulanPSL2", diff --git a/packages/inula/src/dom/DOMExternal.ts b/packages/inula/src/dom/DOMExternal.ts index 001d18f5..aab3e57b 100644 --- a/packages/inula/src/dom/DOMExternal.ts +++ b/packages/inula/src/dom/DOMExternal.ts @@ -22,7 +22,7 @@ import { listenSimulatedDelegatedEvents } from '../event/EventBinding'; import { Callback } from '../renderer/Types'; import { InulaNode } from '../types'; -function createRoot(children: any, container: Container, callback?: Callback) { +export function createTreeRoot(children: any, container: Container, callback?: Callback) { // 清空容器 let child = container.lastChild; while (child) { @@ -56,7 +56,7 @@ function executeRender(children: any, container: Container, callback?: Callback) let treeRoot = container._treeRoot; if (!treeRoot) { - treeRoot = createRoot(children, container, callback); + treeRoot = createTreeRoot(children, container, callback); } else { // container被render过 if (typeof callback === 'function') { diff --git a/packages/inula/src/dom/DOMOperator.ts b/packages/inula/src/dom/DOMOperator.ts index ba032254..ec9407f8 100644 --- a/packages/inula/src/dom/DOMOperator.ts +++ b/packages/inula/src/dom/DOMOperator.ts @@ -21,12 +21,12 @@ import { NSS } from './utils/DomCreator'; import { adjustStyleValue } from './DOMPropertiesHandler/StyleHandler'; import type { VNode } from '../renderer/Types'; import { setInitValue, getPropsWithoutValue, updateValue } from './valueHandler'; -import { compareProps, setDomProps } from './DOMPropertiesHandler/DOMPropertiesHandler'; import { isNativeElement, validateProps } from './validators/ValidateProps'; import { watchValueChange } from './valueHandler/ValueChangeHandler'; import { DomComponent, DomText } from '../renderer/vnode/VNodeTags'; import { updateCommonProp } from './DOMPropertiesHandler/UpdateCommonProp'; import { getCurrentRoot } from '../renderer/RootStack'; +import hostConfig from '../reconciler/hostConfig'; export type Props = Record & { autoFocus?: boolean; @@ -94,7 +94,7 @@ export function initDomProps(dom: Element, tagName: string, rawProps: Props): bo // 初始化DOM属性(不包括value,defaultValue) const isNativeTag = isNativeElement(tagName, props); - setDomProps(dom, props, isNativeTag, true); + hostConfig.setDomProps(dom, props, isNativeTag, true); if (tagName === 'input' || tagName === 'textarea') { // 增加监听value和checked的set、get方法 @@ -121,7 +121,7 @@ export function getPropChangeList( const oldProps: Record = getPropsWithoutValue(type, dom, lastRawProps); const newProps: Record = getPropsWithoutValue(type, dom, nextRawProps); - return compareProps(oldProps, newProps); + return hostConfig.compareProps(oldProps, newProps); } export function isTextChild(type: string, props: Props): boolean { @@ -175,7 +175,7 @@ export function submitDomUpdate(tag: string, vNode: VNode) { updateCommonProp(element, 'checked', newProps.checked, true); } const isNativeTag = isNativeElement(type, newProps); - setDomProps(element, changeList, isNativeTag, false); + hostConfig.setDomProps(element, changeList, isNativeTag, false); updateValue(type, element, newProps); } } diff --git a/packages/inula/src/index.ts b/packages/inula/src/index.ts index 116ab1f2..301dd79f 100644 --- a/packages/inula/src/index.ts +++ b/packages/inula/src/index.ts @@ -71,6 +71,7 @@ import { import { syncUpdates as flushSync } from './renderer/TreeBuilder'; import { toRaw } from './inulax/proxy/ProxyHandler'; +import inulaReconciler from './reconciler'; const Inula = { Children, @@ -122,6 +123,7 @@ const Inula = { Profiler, StrictMode, Suspense, + inulaReconciler, }; export const version = __VERSION__; @@ -178,6 +180,7 @@ export { Profiler, StrictMode, Suspense, + inulaReconciler, }; export * from './types'; diff --git a/packages/inula/src/reconciler/hostConfig.ts b/packages/inula/src/reconciler/hostConfig.ts new file mode 100644 index 00000000..de15fcc5 --- /dev/null +++ b/packages/inula/src/reconciler/hostConfig.ts @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Huawei Technologies Co.,Ltd. + * + * openInula is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +import { setDomProps, compareProps } from '../dom/DOMPropertiesHandler/DOMPropertiesHandler'; +import { + appendChildElement, + clearText, + hideDom, + unHideDom, + initDomProps, + insertDomBefore, + newDom, + newTextDom, + removeChildDom, + submitDomUpdate +} from '../dom/DOMOperator'; + +const hostConfig = { + setDomProps, + compareProps, + newDom, + initDomProps, + newTextDom, + submitDomUpdate, + clearText, + appendChildElement, + insertDomBefore, + removeChildDom, + hideDom, + unHideDom, +}; + +export default hostConfig; diff --git a/packages/inula/src/reconciler/index.ts b/packages/inula/src/reconciler/index.ts new file mode 100644 index 00000000..00102795 --- /dev/null +++ b/packages/inula/src/reconciler/index.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Huawei Technologies Co.,Ltd. + * + * openInula is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +import { createTreeRoot as createContainer } from '../dom/DOMExternal'; +import { getPublicRootInstance } from '../renderer/getPublicRootInstance'; +import { startUpdate as updateContainer } from '../renderer/Renderer'; +import hostConfig from './hostConfig'; + +const inulaReconciler = { + hostConfig, + createContainer, + updateContainer, + getPublicRootInstance +}; + +export default inulaReconciler; diff --git a/packages/inula/src/renderer/getPublicRootInstance.ts b/packages/inula/src/renderer/getPublicRootInstance.ts new file mode 100644 index 00000000..a0bd6d41 --- /dev/null +++ b/packages/inula/src/renderer/getPublicRootInstance.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Huawei Technologies Co.,Ltd. + * + * openInula is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +import {VNode} from './vnode/VNode'; +import {DomComponent, TreeRoot} from './vnode/VNodeTags'; + +export function getPublicRootInstance(container: VNode): any { + const realNode = container.realNode; + if (!realNode.child) { + return null; + } + + switch (realNode.child.tag) { + case TreeRoot: + case DomComponent: + return realNode.child.realNode; + default: + return realNode.child.stateNode; + } +} diff --git a/packages/inula/src/renderer/render/DomComponent.ts b/packages/inula/src/renderer/render/DomComponent.ts index 65044cb2..6b3ad700 100644 --- a/packages/inula/src/renderer/render/DomComponent.ts +++ b/packages/inula/src/renderer/render/DomComponent.ts @@ -17,12 +17,13 @@ import type { VNode } from '../Types'; import type { Props } from '../../dom/DOMOperator'; import { getNamespaceCtx, setNamespaceCtx, resetNamespaceCtx } from '../ContextSaver'; -import { appendChildElement, newDom, initDomProps, getPropChangeList, isTextChild } from '../../dom/DOMOperator'; +import { getPropChangeList, isTextChild } from '../../dom/DOMOperator'; import { FlagUtils } from '../vnode/VNodeFlags'; import { markRef } from './BaseComponent'; import { DomComponent, DomPortal, DomText } from '../vnode/VNodeTags'; import { travelVNodeTree } from '../vnode/VNodeUtils'; import { createChildrenByDiff } from '../diff/nodeDiffComparator'; +import hostConfig from '../../reconciler/hostConfig'; function updateDom(processing: VNode, type: any, newProps: Props) { // 如果oldProps !== newProps,意味着存在更新,并且需要处理其相关的副作用 @@ -65,7 +66,7 @@ export function bubbleRender(processing: VNode) { const parentNamespace = getNamespaceCtx(); // 创建dom - const dom = newDom(type, newProps, parentNamespace, processing); + const dom = hostConfig.newDom(type, newProps, parentNamespace, processing); // 把dom类型的子节点append到parent dom中 const vNode = processing.child; @@ -75,7 +76,7 @@ export function bubbleRender(processing: VNode) { vNode, node => { if (node.tag === DomComponent || node.tag === DomText) { - appendChildElement(dom, node.realNode); + hostConfig.appendChildElement(dom, node.realNode); } }, node => @@ -88,7 +89,7 @@ export function bubbleRender(processing: VNode) { processing.realNode = dom; - if (initDomProps(dom, type, newProps)) { + if (hostConfig.initDomProps(dom, type, newProps)) { FlagUtils.markUpdate(processing); } diff --git a/packages/inula/src/renderer/render/DomText.ts b/packages/inula/src/renderer/render/DomText.ts index f0a5f2e5..7f8bcfad 100644 --- a/packages/inula/src/renderer/render/DomText.ts +++ b/packages/inula/src/renderer/render/DomText.ts @@ -16,8 +16,8 @@ import type { VNode } from '../Types'; import { throwIfTrue } from '../utils/throwIfTrue'; -import { newTextDom } from '../../dom/DOMOperator'; import { FlagUtils } from '../vnode/VNodeFlags'; +import hostConfig from '../../reconciler/hostConfig'; export function captureRender(): VNode | null { return null; @@ -44,6 +44,6 @@ export function bubbleRender(processing: VNode) { ); } // 获得对应节点 - processing.realNode = newTextDom(newText, processing); + processing.realNode = hostConfig.newTextDom(newText, processing); } } diff --git a/packages/inula/src/renderer/submit/LifeCycleHandler.ts b/packages/inula/src/renderer/submit/LifeCycleHandler.ts index 34d34e8d..0e4f439f 100644 --- a/packages/inula/src/renderer/submit/LifeCycleHandler.ts +++ b/packages/inula/src/renderer/submit/LifeCycleHandler.ts @@ -34,15 +34,6 @@ import { } from '../vnode/VNodeTags'; import { FlagUtils, ResetText, Clear, Update, DirectAddition } from '../vnode/VNodeFlags'; import { mergeDefaultProps } from '../render/LazyComponent'; -import { - submitDomUpdate, - clearText, - appendChildElement, - insertDomBefore, - removeChildDom, - hideDom, - unHideDom, -} from '../../dom/DOMOperator'; import { callEffectRemove, callUseEffects, @@ -53,6 +44,7 @@ import { handleSubmitError } from '../ErrorHandler'; import { travelVNodeTree, clearVNode, isDomVNode, getSiblingDom } from '../vnode/VNodeUtils'; import { shouldAutoFocus } from '../../dom/utils/Common'; import { BELONG_CLASS_VNODE_KEY } from '../vnode/VNode'; +import hostConfig from '../../reconciler/hostConfig'; function callComponentWillUnmount(vNode: VNode, instance: any) { try { @@ -143,9 +135,9 @@ function hideOrUnhideAllChildren(vNode, isHidden) { if (node.tag === DomComponent || node.tag === DomText) { if (isHidden) { - hideDom(node.tag, instance); + hostConfig.hideDom(node.tag, instance); } else { - unHideDom(node.tag, instance, node.props); + hostConfig.unHideDom(node.tag, instance, node.props); } } }, @@ -227,7 +219,7 @@ function unmountDomComponents(vNode: VNode): void { unmountNestedVNodes(node); // 在所有子项都卸载后,删除dom树中的节点 - removeChildDom(currentParent, node.realNode); + hostConfig.removeChildDom(currentParent, node.realNode); } else if (node.tag === DomPortal) { if (node.child !== null) { currentParent = node.realNode; @@ -292,9 +284,9 @@ function unmountVNode(vNode: VNode): void { function insertDom(parent, realNode, beforeDom) { if (beforeDom) { - insertDomBefore(parent, realNode, beforeDom); + hostConfig.insertDomBefore(parent, realNode, beforeDom); } else { - appendChildElement(parent, realNode); + hostConfig.appendChildElement(parent, realNode); } } @@ -330,7 +322,7 @@ function submitAddition(vNode: VNode): void { if ((parent!.flags & ResetText) === ResetText) { // 在insert之前先reset - clearText(parentDom); + hostConfig.clearText(parentDom); FlagUtils.removeFlag(parent!, ResetText); } @@ -381,7 +373,7 @@ function submitClear(vNode: VNode): void { } // 在所有子项都卸载后,删除dom树中的节点 - removeChildDom(parentDom, vNode.realNode); + hostConfig.removeChildDom(parentDom, vNode.realNode); const realNodeNext = getSiblingDom(vNode); insertDom(parentDom, cloneDom, realNodeNext); vNode.realNode = cloneDom; @@ -416,7 +408,7 @@ function submitUpdate(vNode: VNode): void { } case DomComponent: case DomText: { - submitDomUpdate(vNode.tag, vNode); + hostConfig.submitDomUpdate(vNode.tag, vNode); break; } case SuspenseComponent: { @@ -431,7 +423,7 @@ function submitUpdate(vNode: VNode): void { } function submitResetTextContent(vNode: VNode) { - clearText(vNode.realNode); + hostConfig.clearText(vNode.realNode); } export {