Compare commits

...

3 Commits

Author SHA1 Message Date
涂旭辉 06458da6db
!33 [inula]<feat> 新增 reconciler 模块
Merge pull request !33 from 涂旭辉/reconciler
2023-10-09 09:04:31 +00:00
13659257719 61ad99bdb1 Merge branch 'master' of https://gitee.com/openInula/inula into reconciler 2023-10-09 16:59:44 +08:00
13659257719 f8c5cb0bbe [inula]<feat> 新增 reconciler 模块 2023-10-09 16:53:51 +08:00
10 changed files with 132 additions and 31 deletions

View File

@ -4,7 +4,7 @@
"keywords": [
"openinula"
],
"version": "0.0.1",
"version": "0.0.1-beta-reconciler-20231009-2",
"homepage": "",
"bugs": "",
"license": "MulanPSL2",

View File

@ -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') {

View File

@ -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<string, any> & {
autoFocus?: boolean;
@ -94,7 +94,7 @@ export function initDomProps(dom: Element, tagName: string, rawProps: Props): bo
// 初始化DOM属性不包括valuedefaultValue
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<string, any> = getPropsWithoutValue(type, dom, lastRawProps);
const newProps: Record<string, any> = 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);
}
}

View File

@ -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';

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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 {