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 { updateVNode } from './vnode/VNodeCreator';
import { TreeRoot } from './vnode/VNodeTags';
import { TreeRoot, DomComponent, DomPortal } from './vnode/VNodeTags';
import { FlagUtils, InitFlag, Interrupted } from './vnode/VNodeFlags';
import { captureVNode } from './render/BaseComponent';
import { checkLoopingUpdateLimit, submitToRender } from './submit/Submit';
@ -18,7 +18,6 @@ import {
setProcessingClassVNode,
setStartVNode
} from './GlobalVar';
import { findDomParent } from './vnode/VNodeUtils';
import {
ByAsync,
BySync,
@ -223,13 +222,21 @@ function buildVNodeTree(treeRoot: VNode) {
if (startVNode.tag !== TreeRoot) { // 不是根节点
// 设置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
if (parentObj !== null) {
const domParent = parentObj.parent;
resetNamespaceCtx(domParent);
setNamespaceCtx(domParent, domParent.outerDom);
if (parent !== null) {
resetNamespaceCtx(parent);
setNamespaceCtx(parent, parent.outerDom);
}
// 恢复父节点的context

View File

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

View File

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

View File

@ -84,28 +84,6 @@ export function updateVNode(vNode: VNode, vNodeProps?: any): 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) {
const vNode = newVirtualNode(Fragment, fragmentKey, fragmentProps);
vNode.shouldUpdate = true;
@ -127,14 +105,30 @@ export function createPortalVNode(portal) {
}
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);
vNode.type = type;
vNode.shouldUpdate = true;
if (isLazy) {
vNode.isLazyComponent = isLazy;
vNode.lazyType = type;
}
return vNode;

View File

@ -93,7 +93,6 @@ export function clearVNode(vNode: VNode) {
vNode.oldState = null;
vNode.oldRef = null;
vNode.oldChild = null;
vNode.flags = InitFlag;
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 {
return travelVNodeTree(vNode, (node) => {
if (node.tag === DomComponent || node.tag === DomText) {