Match-id-93334d78c8b399ade8afbf64ec34ab13e1965ee4

This commit is contained in:
* 2021-12-22 20:42:14 +08:00 committed by *
parent 8847bf3cb2
commit 35777afb6d
12 changed files with 839 additions and 0 deletions

View File

@ -0,0 +1,131 @@
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 {FlagUtils} from '../vnode/VNodeFlags';
import {createVNodeChildren, markRef} from './BaseComponent';
import {DomComponent, DomPortal, DomText} from '../vnode/VNodeTags';
import {getFirstChild, travelVNodeTree} from '../vnode/VNodeUtils';
export function captureRender(processing: VNode): Array<VNode> | null {
return captureDomComponent(processing);
}
export function bubbleRender(processing: VNode) {
resetNamespaceCtx(processing);
const type = processing.type;
const newProps = processing.props;
if (!processing.isCreated && processing.realNode != null) {
// 更新dom属性
updateDom(
processing,
type,
newProps,
);
if (processing.oldRef !== processing.ref) {
FlagUtils.markRef(processing);
}
} else {
const parentNamespace = getNamespaceCtx();
// 创建dom
const dom = newDom(
type,
newProps,
parentNamespace,
processing,
);
appendAllChildren(dom, processing);
processing.realNode = dom;
if (initDomProps(dom, type, newProps)) {
FlagUtils.markUpdate(processing);
}
// 处理ref导致的更新
if (processing.ref !== null) {
FlagUtils.markRef(processing);
}
}
}
function captureDomComponent(processing: VNode): Array<VNode> | null {
setNamespaceCtx(processing);
const type = processing.type;
const newProps = processing.props;
const oldProps = !processing.isCreated ? processing.oldProps : null;
let nextChildren = newProps.children;
const isDirectTextChild = isTextChild(type, newProps);
if (isDirectTextChild) {
// 如果为文本节点,则认为没有子节点
nextChildren = null;
} else if (oldProps !== null && isTextChild(type, oldProps)) {
// 将纯文本的子节点改为vNode节点
FlagUtils.markContentReset(processing);
}
markRef(processing);
processing.children = createVNodeChildren(processing, nextChildren);
return processing.children;
}
// 把dom类型的子节点append到parent dom中
function appendAllChildren(parent: Element, processing: VNode) {
const vNode = getFirstChild(processing);
if (vNode === null) {
return;
}
// 向下递归它的子节点,查找所有终端节点。
travelVNodeTree(vNode, (node) => {
if (node.tag === DomComponent || node.tag === DomText) {
appendChildElement(parent, node.realNode);
}
}, (node) => {
// 已经append到父节点或者是DomPortal都不需要处理child了
return node.tag === DomComponent || node.tag === DomText || node.tag === DomPortal;
}, processing);
}
function updateDom(
processing: VNode,
type: any,
newProps: Props,
) {
// 如果oldProps !== newProps意味着存在更新并且需要处理其相关的副作用
const oldProps = processing.oldProps;
if (oldProps === newProps) {
// 如果props没有发生变化即使它的children发生了变化我们也不会改变它
return;
}
const dom: Element = processing.realNode;
const changeList = getPropChangeList(
dom,
type,
oldProps,
newProps,
);
processing.changeList = changeList;
// 标记为更新
FlagUtils.markUpdate(processing);
}

View File

@ -0,0 +1,29 @@
import type { VNode } from '../Types';
import { resetNamespaceCtx, setNamespaceCtx } from '../ContextSaver';
import { createChildrenByDiff } from '../diff/nodeDiffComparator';
import { createVNodeChildren } from './BaseComponent';
import { prePortal } from '../../dom/DOMOperator';
export function captureRender(processing: VNode): Array<VNode> | null {
return capturePortalComponent(processing);
}
export function bubbleRender(processing: VNode) {
resetNamespaceCtx(processing);
if (processing.isCreated) {
prePortal(processing.outerDom);
}
}
function capturePortalComponent(processing: VNode) {
setNamespaceCtx(processing, processing.outerDom);
const newElements = processing.props;
if (processing.isCreated) {
processing.children = createChildrenByDiff(processing, [], newElements);
} else {
processing.children = createVNodeChildren(processing, newElements);
}
return processing.children;
}

View File

@ -0,0 +1,35 @@
import type {VNode} from '../Types';
import {throwIfTrue} from '../utils/throwIfTrue';
import {newTextDom} from '../../dom/DOMOperator';
import {FlagUtils} from '../vnode/VNodeFlags';
export function captureRender(): VNode | null {
return null;
}
export function bubbleRender(processing: VNode) {
const newText = processing.props;
if (!processing.isCreated && processing.realNode != null) { // 更新
const oldText = processing.oldProps;
// 如果文本不同,将其标记为更新
if (oldText !== newText) {
FlagUtils.markUpdate(processing);
}
} else { // 初始化
if (typeof newText !== 'string') {
// 如果存在bug可能出现这种情况
throwIfTrue(
processing.realNode === null,
'We must have new text for new mounted node. This error is likely ' +
'caused by a bug in Horizon. Please file an issue.',
);
}
// 获得对应节点
processing.realNode = newTextDom(
newText,
processing,
);
}
}

View File

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

View File

@ -0,0 +1,14 @@
import type {VNode} from '../Types';
import {createVNodeChildren} from './BaseComponent';
export function captureRender(processing: VNode): Array<VNode> | null {
return captureFragment(processing);
}
export function bubbleRender() {}
function captureFragment(processing: VNode) {
const newElement = processing.props;
processing.children = createVNodeChildren(processing, newElement);
return processing.children;
}

View File

@ -0,0 +1,100 @@
import type {VNode} from '../Types';
import {mergeDefaultProps} from './LazyComponent';
import {getOldContext} from '../components/context/CompatibleContext';
import {resetDepContexts} from '../components/context/Context';
import {exeFunctionHook} from '../hooks/HookMain';
import {createVNodeChildren} from './BaseComponent';
import {ForwardRef} from '../vnode/VNodeTags';
import {FlagUtils, Update} from '../vnode/VNodeFlags';
import {getContextChangeCtx} from '../ContextSaver';
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
// 在useState, useReducer的时候会触发state变化
let stateChange = false;
export function captureRender(processing: VNode, shouldUpdate?: boolean): Array<VNode> | null {
const Component = processing.type;
const unresolvedProps = processing.props;
const resolvedProps =
processing.isLazyComponent
? mergeDefaultProps(Component, unresolvedProps)
: unresolvedProps;
return captureFunctionComponent(
processing,
Component,
resolvedProps,
shouldUpdate
);
}
export function bubbleRender() {}
export function captureFunctionComponent(
processing: VNode,
funcComp: any,
nextProps: any,
shouldUpdate?: boolean
) {
let context;
if (processing.tag !== ForwardRef) {
context = getOldContext(processing, funcComp, true);
}
resetDepContexts(processing);
const isCanReuse = checkIfCanReuseChildren(processing, shouldUpdate);
// 在执行exeFunctionHook前先设置stateChange为false
setStateChange(false);
const newElements = exeFunctionHook(
processing.tag === ForwardRef ? funcComp.render : funcComp,
nextProps,
processing.tag === ForwardRef ? processing.ref : context,
processing,
);
// 这里需要判断是否可以复用因为函数组件比起其他组价多了context和stateChange两个因素
if (isCanReuse && !isStateChange()) {
FlagUtils.removeFlag(processing, Update);
return onlyUpdateChildVNodes(processing);
}
processing.children = createVNodeChildren(processing, newElements);
return processing.children;
}
// 判断children是否可以复用
function checkIfCanReuseChildren(processing: VNode, shouldUpdate?: boolean) {
let isCanReuse = true;
if (!processing.isCreated) {
const oldProps = processing.oldProps;
const newProps = processing.props;
// 如果props或者context改变了
if (oldProps !== newProps || getContextChangeCtx() || processing.isDepContextChange) {
isCanReuse = false;
} else {
if (shouldUpdate && processing.suspenseChildThrow) {
// 使用完后恢复
processing.suspenseChildThrow = false;
isCanReuse = false;
}
}
} else {
isCanReuse = false;
}
return isCanReuse;
}
export function setStateChange(isUpdate) {
stateChange = isUpdate;
}
export function isStateChange() {
return stateChange;
}

View File

@ -0,0 +1,41 @@
import type {VNode} from '../Types';
import {mergeDefaultProps} from './LazyComponent';
import {ClassComponent} from '../vnode/VNodeTags';
import {resetDepContexts} from '../components/context/Context';
import {getIncompleteClassComponent} from './ClassComponent';
import {
isOldProvider,
resetOldCtx,
cacheOldCtx,
} from '../components/context/CompatibleContext';
export function captureRender(processing: VNode): Array<VNode> | null {
const Component = processing.type;
const unresolvedProps = processing.props;
const resolvedProps =
processing.isLazyComponent
? mergeDefaultProps(Component, unresolvedProps)
: unresolvedProps;
return captureIncompleteClassComponent(processing, Component, resolvedProps);
}
export function bubbleRender(processing: VNode) {
// 处理与类组件相同。
const Component = processing.type;
if (isOldProvider(Component)) {
resetOldCtx(processing);
}
}
function captureIncompleteClassComponent(processing, Component, nextProps) {
processing.tag = ClassComponent;
const hasOldContext = isOldProvider(Component);
cacheOldCtx(processing, hasOldContext);
resetDepContexts(processing);
return getIncompleteClassComponent(Component, processing, nextProps);
}

View File

@ -0,0 +1,82 @@
import type {VNode} from '../Types';
import {FlagUtils} from '../vnode/VNodeFlags';
import {getLazyVNodeTag} from '../vnode/VNodeCreator';
import {
ClassComponent,
ForwardRef,
FunctionComponent,
MemoComponent,
} from '../vnode/VNodeTags';
import {throwIfTrue} from '../utils/throwIfTrue';
import {captureFunctionComponent} from './FunctionComponent';
import {captureClassComponent} from './ClassComponent';
import {captureMemoComponent} from './MemoComponent';
export function captureRender(processing: VNode, shouldUpdate: boolean): VNode | null {
return captureLazyComponent(processing, processing.type, shouldUpdate);
}
export function bubbleRender() {}
const LazyRendererMap = {
[FunctionComponent]: captureFunctionComponent,
[ClassComponent]: captureClassComponent,
[ForwardRef]: captureFunctionComponent,
[MemoComponent]: captureMemoComponent,
};
function captureLazyComponent(
processing,
lazyComponent,
shouldUpdate,
) {
if (!processing.isCreated) {
// 每次加载lazy都当作mount来处理
processing.isCreated = true;
FlagUtils.markAddition(processing);
}
const Component = lazyComponent._load(lazyComponent._content);
// ======================loaded===============================
// 加载得到的Component存在type中
processing.type = Component;
const lazyVNodeTag = processing.tag = getLazyVNodeTag(Component);
const lazyVNodeProps = mergeDefaultProps(Component, processing.props);
const lazyRender = LazyRendererMap[lazyVNodeTag];
if (lazyRender) {
if (lazyVNodeTag === MemoComponent) {
// Memo要特殊处理
const memoVNodeProps = mergeDefaultProps(Component.type, lazyVNodeProps); // 需要整合defaultProps
return lazyRender(processing, Component, memoVNodeProps, shouldUpdate);
} else {
return lazyRender(processing, Component, lazyVNodeProps, false);
}
} else {
// lazy加载的组件类型未受支持
throwIfTrue(
true,
'Element type is invalid. Received a promise that resolves to: %s. ' +
'Lazy element type must resolve to a class or function.%s',
Component,
'',
);
}
}
export function mergeDefaultProps(Component: any, props: object): object {
if (Component && Component.defaultProps) {
const clonedProps = {...props};
const defaultProps = Component.defaultProps;
Object.keys(defaultProps).forEach(key => {
if (clonedProps[key] === undefined) {
clonedProps[key] = defaultProps[key];
}
});
return clonedProps;
}
return props;
}

View File

@ -0,0 +1,61 @@
import type {VNode} from '../Types';
import {mergeDefaultProps} from './LazyComponent';
import {updateVNode, createVNode, onlyUpdateChildVNodes, updateVNodePath} from '../vnode/VNodeCreator';
import {shallowCompare} from '../utils/compare';
import {
TYPE_FRAGMENT,
TYPE_PROFILER,
TYPE_STRICT_MODE,
} from '../utils/elementType';
import {Fragment} from '../vnode/VNodeTags';
export function captureRender(processing: VNode, shouldUpdate: boolean): Array<VNode> | null {
return captureMemoComponent(processing, shouldUpdate);
}
export function bubbleRender() {}
export function captureMemoComponent(
processing: VNode,
shouldUpdate: boolean,
): Array<VNode> | null {
const Component = processing.type;
// 合并 函数组件或类组件 的defaultProps
const newProps = mergeDefaultProps(Component, processing.props);
if (processing.isCreated) {
let newChild = null;
const type = Component.type;
if (type === TYPE_STRICT_MODE || type === TYPE_FRAGMENT || type === TYPE_PROFILER) {
newChild = createVNode(Fragment, null, newProps.children);
} else {
newChild = createVNode('props', type, null, newProps, processing);
}
newChild.parent = processing;
newChild.ref = processing.ref;
updateVNodePath(newChild);
processing.children = [newChild];
return processing.children;
}
const firstChild = processing.children.length ? processing.children[0] : null; // Memo只有一个child
if (!shouldUpdate) {
const oldProps = firstChild.props;
// 默认是浅对比
const compare = Component.compare ? Component.compare : shallowCompare;
if (compare(oldProps, newProps) && processing.oldRef === processing.ref) {
return onlyUpdateChildVNodes(processing);
}
}
const newChild = updateVNode(firstChild, newProps);
newChild.parent = processing;
newChild.cIndex = 0;
updateVNodePath(newChild);
newChild.ref = processing.ref;
processing.children = [newChild];
return processing.children;
}

View File

@ -0,0 +1,239 @@
import type {VNode, PromiseType} from '../Types';
import {FlagUtils, Interrupted} from '../vnode/VNodeFlags';
import {createVNode, onlyUpdateChildVNodes, updateVNode, updateVNodePath} from '../vnode/VNodeCreator';
import {
ClassComponent,
IncompleteClassComponent,
SuspenseComponent,
Fragment,
} from '../vnode/VNodeTags';
import {pushForceUpdate} from '../UpdateHandler';
import {launchUpdateFromVNode, tryRenderRoot} from '../TreeBuilder';
import {updateShouldUpdateOfTree} from '../vnode/VNodeShouldUpdate';
import {getContextChangeCtx} from '../ContextSaver';
export enum SuspenseChildStatus {
Init = '',
ShowChild = 'showChild',
ShowFallback = 'showFallback',
}
export function captureRender(processing: VNode, shouldUpdate: boolean): Array<VNode> | VNode | null {
if (
!processing.isCreated &&
processing.oldProps === processing.props &&
!getContextChangeCtx() &&
!shouldUpdate
) {
if (processing.suspenseChildStatus === SuspenseChildStatus.ShowFallback) {
// 当显示fallback时suspense的子组件要更新
return updateFallback(processing);
}
return onlyUpdateChildVNodes(processing);
}
return captureSuspenseComponent(processing);
}
function updateFallback(processing: VNode): Array<VNode> | VNode | null {
const childFragment: VNode = processing.children[0];
if (childFragment.childShouldUpdate) {
if (processing.promiseResolve) {
// promise已完成展示promise返回的新节点
return captureSuspenseComponent(processing);
} else {
// promise未完成继续显示fallback不需要继续刷新子节点
const fallbackFragment: VNode = processing.children[1];
childFragment.childShouldUpdate = false;
fallbackFragment.childShouldUpdate = false;
return null;
}
} else {
const children = onlyUpdateChildVNodes(processing);
if (children !== null) {
// child不需要更新跳过child处理fallback
return children[1];
} else {
return null;
}
}
}
export function bubbleRender(processing: VNode) {
if (processing.suspenseChildStatus === SuspenseChildStatus.ShowFallback
|| (!processing.isCreated && processing.oldSuspenseChildStatus === SuspenseChildStatus.ShowFallback)
) {
FlagUtils.markUpdate(processing);
}
return null;
}
export function captureSuspenseComponent(processing: VNode) {
const nextProps = processing.props;
// suspense被捕获后需要展示fallback
const showFallback = processing.suspenseDidCapture;
if (showFallback) {
processing.suspenseDidCapture = false;
const nextFallbackChildren = nextProps.fallback;
return createFallback(processing, nextFallbackChildren);
} else {
const newChildren = nextProps.children;
return createSuspenseChildren(processing, newChildren);
}
}
// 创建子节点
function createSuspenseChildren(processing: VNode, newChildren) {
let childFragment: VNode;
if (!processing.isCreated) {
const oldChildFragment: VNode = processing.children[0];
const oldFallbackFragment: VNode | null = processing.children.length > 1 ? processing.children[1] : null;
childFragment = updateVNode(oldChildFragment);
// 将Suspense新的子参数传给子Fragment
childFragment.props = processing.props.children;
childFragment.shouldUpdate = true;
// 删除fallback
if (oldFallbackFragment !== null) {
FlagUtils.setDeletion(oldFallbackFragment);
processing.dirtyNodes = [oldFallbackFragment];
}
// SuspenseComponent 中使用
processing.suspenseChildStatus = SuspenseChildStatus.ShowChild;
} else {
childFragment = createVNode(Fragment, null, newChildren);
}
childFragment.parent = processing;
childFragment.cIndex = 0;
updateVNodePath(childFragment);
processing.children = [childFragment];
processing.promiseResolve = false;
return processing.children;
}
// 创建fallback子节点
function createFallback(processing: VNode, fallbackChildren) {
const childFragment: VNode = processing.children[0];
let fallbackFragment;
childFragment.childShouldUpdate = false;
if (!processing.isCreated) {
const oldFallbackFragment: VNode | null = processing.oldChildren.length > 1 ? processing.oldChildren[1] : null;
if (oldFallbackFragment !== null) {
fallbackFragment = updateVNode(oldFallbackFragment, fallbackChildren);
} else {
fallbackFragment = createVNode(Fragment, null, fallbackChildren);
FlagUtils.markAddition(fallbackFragment);
}
} else {
// 创建
fallbackFragment = createVNode(Fragment, null, fallbackChildren);
}
processing.children = [childFragment, fallbackFragment];
childFragment.parent = processing;
fallbackFragment.parent = processing;
fallbackFragment.eIndex = 1;
fallbackFragment.cIndex = 1;
updateVNodePath(fallbackFragment);
processing.suspenseChildStatus = SuspenseChildStatus.ShowFallback;
return [fallbackFragment];
}
// 处理Suspense子组件抛出的promise
export function handleSuspenseChildThrowError(parent: VNode, processing: VNode, error: any): boolean {
let vNode = parent;
// 向上找到最近的不在fallback状态的Suspense并触发重新渲染
do {
if (vNode.tag === SuspenseComponent && canCapturePromise(vNode)) {
if (vNode.suspensePromises === null) {
vNode.suspensePromises = new Set();
}
vNode.suspensePromises.add(error);
processing.suspenseChildThrow = true;
// 移除生命周期flag 和 中断flag
FlagUtils.removeLifecycleEffectFlags(processing);
FlagUtils.removeFlag(processing, Interrupted);
if (processing.tag === ClassComponent) {
if (processing.isCreated) {
// 渲染类组件场景要标志未完成否则会触发componentWillUnmount
processing.tag = IncompleteClassComponent;
} else {
// 类组件更新标记强制更新否则被memo等优化跳过
pushForceUpdate(processing);
launchUpdateFromVNode(processing);
}
}
// 应该抛出promise未完成更新标志待更新
processing.shouldUpdate = true;
vNode.suspenseDidCapture = true;
launchUpdateFromVNode(vNode);
return true;
}
vNode = vNode.parent;
} while (vNode !== null);
return false;
}
function canCapturePromise(vNode: VNode): boolean {
return vNode.suspenseChildStatus !== SuspenseChildStatus.ShowFallback && vNode.props.fallback !== undefined;
}
const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
// 对于每个promise添加一个侦听器以便当它resolve时重新渲染
export function listenToPromise(suspenseVNode: VNode) {
const promises: Set<PromiseType<any>> | null = suspenseVNode.suspensePromises;
if (promises !== null) {
suspenseVNode.suspensePromises = null;
// 记录已经监听的 promise
let promiseCache = suspenseVNode.realNode;
if (promiseCache === null) {
// @ts-ignore
promiseCache = suspenseVNode.realNode = new PossiblyWeakSet();
}
promises.forEach(promise => {
const resole = resolvePromise.bind(null, suspenseVNode, promise);
if (!promiseCache.has(promise)) {
promiseCache.add(promise);
// 监听promise
promise.then(resole, resole);
}
});
}
}
function resolvePromise(suspenseVNode: VNode, promise: PromiseType<any>) {
const promiseCache = suspenseVNode.realNode;
if (promiseCache !== null) {
promiseCache.delete(promise);
}
suspenseVNode.promiseResolve = true;
const root = updateShouldUpdateOfTree(suspenseVNode);
if (root !== null) {
tryRenderRoot(root);
}
}

View File

@ -0,0 +1,42 @@
import type {VNode} from '../Types';
import {throwIfTrue} from '../utils/throwIfTrue';
import {processUpdates} from '../UpdateHandler';
import {createVNodeChildren} from './BaseComponent';
import {resetNamespaceCtx, setNamespaceCtx} from '../ContextSaver';
import {resetOldCtx} from '../components/context/CompatibleContext';
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
export function captureRender(processing: VNode): VNode | null {
return updateTreeRoot(processing);
}
export function bubbleRender(processing: VNode) {
resetNamespaceCtx(processing);
resetOldCtx(processing);
}
function updateTreeRoot(processing) {
setNamespaceCtx(processing, processing.outerDom);
const updates = processing.updates;
throwIfTrue(
processing.isCreated || updates === null,
'If the root does not have an updates, we should have already ' +
'bailed out. This error is likely caused by a bug. Please ' +
'file an issue.',
);
const newProps = processing.props;
const oldState = processing.state;
const oldElement = oldState !== null ? oldState.element : null;
processUpdates(processing, null, newProps);
const newState = processing.state;
// 为了保持对Dev Tools的兼容这里还是使用element
const newElement = newState.element;
if (newElement === oldElement) {
return onlyUpdateChildVNodes(processing);
}
processing.children = createVNodeChildren(processing, newElement);
return processing.children;
}

View File

@ -0,0 +1,56 @@
import * as BaseComponentRender from './BaseComponent';
import * as ClassComponentRender from './ClassComponent';
import * as ContextConsumerRender from './ContextConsumer';
import * as ContextProviderRender from './ContextProvider';
import * as ForwardRefRender from './ForwardRef';
import * as FragmentRender from './Fragment';
import * as FunctionComponentRender from './FunctionComponent';
import * as DomComponentRender from './DomComponent';
import * as DomPortalRender from './DomPortal';
import * as TreeRootRender from './TreeRoot';
import * as DomTextRender from './DomText';
import * as IncompleteClassComponentRender from './IncompleteClassComponent';
import * as ClsOrFunComponentRender from './ClsOrFunComponent';
import * as LazyComponentRender from './LazyComponent';
import * as MemoComponentRender from './MemoComponent';
import * as SuspenseComponentRender from './SuspenseComponent';
import {
ClassComponent,
ContextConsumer,
ContextProvider,
ForwardRef,
Fragment,
FunctionComponent,
DomComponent,
DomPortal,
TreeRoot,
DomText,
IncompleteClassComponent,
ClsOrFunComponent,
LazyComponent,
MemoComponent,
SuspenseComponent,
} from '../vnode/VNodeTags';
export {
BaseComponentRender
}
export default {
[ClassComponent]: ClassComponentRender,
[ContextConsumer]: ContextConsumerRender,
[ContextProvider]: ContextProviderRender,
[ForwardRef]: ForwardRefRender,
[Fragment]: FragmentRender,
[FunctionComponent]: FunctionComponentRender,
[DomComponent]: DomComponentRender,
[DomPortal]: DomPortalRender,
[TreeRoot]: TreeRootRender,
[DomText]: DomTextRender,
[IncompleteClassComponent]: IncompleteClassComponentRender,
[ClsOrFunComponent]: ClsOrFunComponentRender,
[LazyComponent]: LazyComponentRender,
[MemoComponent]: MemoComponentRender,
[SuspenseComponent]: SuspenseComponentRender,
}