Match-id-ddc72092565c7daebcfd35b019c5f5422e0293d6

This commit is contained in:
* 2022-02-18 11:26:53 +08:00 committed by *
commit 391977a312
5 changed files with 80 additions and 60 deletions

View File

@ -2,7 +2,7 @@ import type { VNode } from './Types';
import { callRenderQueueImmediate, pushRenderCallback } from './taskExecutor/RenderQueue'; import { callRenderQueueImmediate, pushRenderCallback } from './taskExecutor/RenderQueue';
import { updateVNode } from './vnode/VNodeCreator'; import { updateVNode } from './vnode/VNodeCreator';
import { TreeRoot } from './vnode/VNodeTags'; import { TreeRoot, DomComponent, DomPortal } from './vnode/VNodeTags';
import { FlagUtils, InitFlag, Interrupted } from './vnode/VNodeFlags'; import { FlagUtils, InitFlag, Interrupted } from './vnode/VNodeFlags';
import { captureVNode } from './render/BaseComponent'; import { captureVNode } from './render/BaseComponent';
import { checkLoopingUpdateLimit, submitToRender } from './submit/Submit'; import { checkLoopingUpdateLimit, submitToRender } from './submit/Submit';
@ -18,7 +18,6 @@ import {
setProcessingClassVNode, setProcessingClassVNode,
setStartVNode setStartVNode
} from './GlobalVar'; } from './GlobalVar';
import { findDomParent } from './vnode/VNodeUtils';
import { import {
ByAsync, ByAsync,
BySync, BySync,
@ -223,13 +222,21 @@ function buildVNodeTree(treeRoot: VNode) {
if (startVNode.tag !== TreeRoot) { // 不是根节点 if (startVNode.tag !== TreeRoot) { // 不是根节点
// 设置namespace用于createElement // 设置namespace用于createElement
const parentObj = findDomParent(startVNode); let parent = startVNode.parent;
while (parent !== null) {
const tag = parent.tag;
if (tag === DomComponent) {
break;
} else if (tag === TreeRoot || tag === DomPortal) {
break;
}
parent = parent.parent;
}
// 当在componentWillUnmount中调用setStateparent可能是null因为startVNode会被clear // 当在componentWillUnmount中调用setStateparent可能是null因为startVNode会被clear
if (parentObj !== null) { if (parent !== null) {
const domParent = parentObj.parent; resetNamespaceCtx(parent);
resetNamespaceCtx(domParent); setNamespaceCtx(parent, parent.outerDom);
setNamespaceCtx(domParent, domParent.outerDom);
} }
// 恢复父节点的context // 恢复父节点的context

View File

@ -39,7 +39,7 @@ import {
travelVNodeTree, travelVNodeTree,
clearVNode, clearVNode,
isDomVNode, isDomVNode,
findDomParent, getSiblingDom, getSiblingDom,
} from '../vnode/VNodeUtils'; } from '../vnode/VNodeUtils';
import { shouldAutoFocus } from '../../dom/utils/Common'; import { shouldAutoFocus } from '../../dom/utils/Common';
@ -220,9 +220,22 @@ function unmountNestedVNodes(vNode: VNode): void {
} }
function submitAddition(vNode: VNode): void { function submitAddition(vNode: VNode): void {
const { parent, parentDom } = findDomParent(vNode); let parent = vNode.parent;
let parentDom;
let tag;
while (parent !== null) {
tag = parent.tag;
if (tag === DomComponent) {
parentDom = parent.realNode;
break;
} else if (tag === TreeRoot || tag === DomPortal) {
parentDom = parent.outerDom;
break;
}
parent = parent.parent;
}
if ((vNode.flags & ResetText) === ResetText) { if ((parent.flags & ResetText) === ResetText) {
// 在insert之前先reset // 在insert之前先reset
clearText(parentDom); clearText(parentDom);
FlagUtils.removeFlag(parent, ResetText); FlagUtils.removeFlag(parent, ResetText);
@ -270,8 +283,19 @@ function unmountDomComponents(vNode: VNode): void {
travelVNodeTree(vNode, (node) => { travelVNodeTree(vNode, (node) => {
if (!currentParentIsValid) { if (!currentParentIsValid) {
const parentObj = findDomParent(node); let parent = node.parent;
currentParent = parentObj.parentDom; let tag;
while (parent !== null) {
tag = parent.tag;
if (tag === DomComponent) {
currentParent = parent.realNode;
break;
} else if (tag === TreeRoot || tag === DomPortal) {
currentParent = parent.outerDom;
break;
}
parent = parent.parent;
}
currentParentIsValid = true; currentParentIsValid = true;
} }
@ -315,8 +339,20 @@ function submitClear(vNode: VNode): void {
} }
} }
const parentObj = findDomParent(vNode); let parent = vNode.parent;
const currentParent = parentObj.parentDom; let parentDom;
let tag;
while (parent !== null) {
tag = parent.tag;
if (tag === DomComponent) {
parentDom = parent.realNode;
break;
} else if (tag === TreeRoot || tag === DomPortal) {
parentDom = parent.outerDom;
break;
}
parent = parent.parent;
}
let clearChild = vNode.clearChild as VNode; // 上次渲染的child保存在clearChild属性中 let clearChild = vNode.clearChild as VNode; // 上次渲染的child保存在clearChild属性中
// 卸载 clearChild 和 它的兄弟节点 // 卸载 clearChild 和 它的兄弟节点
while(clearChild) { while(clearChild) {
@ -327,9 +363,9 @@ function submitClear(vNode: VNode): void {
} }
// 在所有子项都卸载后删除dom树中的节点 // 在所有子项都卸载后删除dom树中的节点
removeChildDom(currentParent, vNode.realNode); removeChildDom(parentDom, vNode.realNode);
const realNodeNext = getSiblingDom(vNode); const realNodeNext = getSiblingDom(vNode);
insertDom(currentParent, cloneDom, realNodeNext); insertDom(parentDom, cloneDom, realNodeNext);
vNode.realNode = cloneDom; vNode.realNode = cloneDom;
attachRef(vNode); attachRef(vNode);
FlagUtils.removeFlag(vNode, Clear); FlagUtils.removeFlag(vNode, Clear);

View File

@ -136,6 +136,8 @@ export class VNode {
case LazyComponent: case LazyComponent:
this.realNode = null; this.realNode = null;
this.stateCallbacks = null; this.stateCallbacks = null;
this.isLazyComponent = true;
this.lazyType = null;
break; break;
case Fragment: case Fragment:
break; break;

View File

@ -84,28 +84,6 @@ export function updateVNode(vNode: VNode, vNodeProps?: any): VNode {
return vNode; return vNode;
} }
function getVNodeTag(type: any) {
let vNodeTag = ClsOrFunComponent;
let isLazy = false;
const componentType = typeof type;
if (componentType === 'function') {
if (isClassComponent(type)) {
vNodeTag = ClassComponent;
}
} else if (componentType === 'string') {
vNodeTag = DomComponent;
} else if (type === TYPE_SUSPENSE) {
vNodeTag = SuspenseComponent;
} else if (componentType === 'object' && type !== null && typeMap[type.vtype]) {
vNodeTag = typeMap[type.vtype];
isLazy = type.vtype === TYPE_LAZY;
} else {
throw Error(`Component type is invalid, got: ${type == null ? type : componentType}`);
}
return { vNodeTag, isLazy };
}
export function createFragmentVNode(fragmentKey, fragmentProps) { export function createFragmentVNode(fragmentKey, fragmentProps) {
const vNode = newVirtualNode(Fragment, fragmentKey, fragmentProps); const vNode = newVirtualNode(Fragment, fragmentKey, fragmentProps);
vNode.shouldUpdate = true; vNode.shouldUpdate = true;
@ -127,14 +105,30 @@ export function createPortalVNode(portal) {
} }
export function createUndeterminedVNode(type, key, props) { export function createUndeterminedVNode(type, key, props) {
const { vNodeTag, isLazy } = getVNodeTag(type); let vNodeTag = ClsOrFunComponent;
let isLazy = false;
const componentType = typeof type;
if (componentType === 'function') {
if (isClassComponent(type)) {
vNodeTag = ClassComponent;
}
} else if (componentType === 'string') {
vNodeTag = DomComponent;
} else if (type === TYPE_SUSPENSE) {
vNodeTag = SuspenseComponent;
} else if (componentType === 'object' && type !== null && typeMap[type.vtype]) {
vNodeTag = typeMap[type.vtype];
isLazy = type.vtype === TYPE_LAZY;
} else {
throw Error(`Component type is invalid, got: ${type == null ? type : componentType}`);
}
const vNode = newVirtualNode(vNodeTag, key, props); const vNode = newVirtualNode(vNodeTag, key, props);
vNode.type = type; vNode.type = type;
vNode.shouldUpdate = true; vNode.shouldUpdate = true;
if (isLazy) { if (isLazy) {
vNode.isLazyComponent = isLazy;
vNode.lazyType = type; vNode.lazyType = type;
} }
return vNode; return vNode;

View File

@ -93,7 +93,6 @@ export function clearVNode(vNode: VNode) {
vNode.oldState = null; vNode.oldState = null;
vNode.oldRef = null; vNode.oldRef = null;
vNode.oldChild = null; vNode.oldChild = null;
vNode.flags = InitFlag;
vNode.toUpdateNodes = null; vNode.toUpdateNodes = null;
@ -114,24 +113,6 @@ function isDomContainer(vNode: VNode): boolean {
); );
} }
// 找到DOM类型的父
export function findDomParent(vNode: VNode) {
let parent = vNode.parent;
while (parent !== null) {
switch (parent.tag) {
case DomComponent:
return {parent, parentDom: parent.realNode};
case TreeRoot:
case DomPortal:
return {parent, parentDom: parent.outerDom};
}
parent = parent.parent;
}
return null;
}
export function findDomVNode(vNode: VNode): VNode | null { export function findDomVNode(vNode: VNode): VNode | null {
return travelVNodeTree(vNode, (node) => { return travelVNodeTree(vNode, (node) => {
if (node.tag === DomComponent || node.tag === DomText) { if (node.tag === DomComponent || node.tag === DomText) {