Match-id-70d03a8fc008ccce49a3f8517fc56c3d6ecbcf98

This commit is contained in:
* 2022-03-06 11:44:13 +08:00 committed by *
commit a1c73a6e2f
21 changed files with 106 additions and 149 deletions

View File

@ -19,7 +19,7 @@ import {
} from './valueHandler'; } from './valueHandler';
import { import {
compareProps, compareProps,
setDomProps, updateDomProps setDomProps,
} from './DOMPropertiesHandler/DOMPropertiesHandler'; } from './DOMPropertiesHandler/DOMPropertiesHandler';
import { isNativeElement, validateProps } from './validators/ValidateProps'; import { isNativeElement, validateProps } from './validators/ValidateProps';
import { watchValueChange } from './valueHandler/ValueChangeHandler'; import { watchValueChange } from './valueHandler/ValueChangeHandler';
@ -91,7 +91,8 @@ export function initDomProps(dom: Element, tagName: string, rawProps: Props): bo
const props: Object = getPropsWithoutValue(tagName, dom, rawProps); const props: Object = getPropsWithoutValue(tagName, dom, rawProps);
// 初始化DOM属性不包括valuedefaultValue // 初始化DOM属性不包括valuedefaultValue
setDomProps(tagName, dom, props); const isNativeTag = isNativeElement(tagName, props);
setDomProps(dom, props, isNativeTag, true);
if (tagName === 'input' || tagName === 'textarea') { if (tagName === 'input' || tagName === 'textarea') {
// 增加监听value和checked的set、get方法 // 增加监听value和checked的set、get方法
@ -110,7 +111,7 @@ export function getPropChangeList(
type: string, type: string,
lastRawProps: Props, lastRawProps: Props,
nextRawProps: Props, nextRawProps: Props,
): Map<string, any> { ): Object {
// 校验两个对象的不同 // 校验两个对象的不同
validateProps(type, nextRawProps); validateProps(type, nextRawProps);
@ -118,8 +119,7 @@ export function getPropChangeList(
const oldProps: Object = getPropsWithoutValue(type, dom, lastRawProps); const oldProps: Object = getPropsWithoutValue(type, dom, lastRawProps);
const newProps: Object = getPropsWithoutValue(type, dom, nextRawProps); const newProps: Object = getPropsWithoutValue(type, dom, nextRawProps);
const changeList = compareProps(oldProps, newProps); return compareProps(oldProps, newProps);
return changeList;
} }
export function isTextChild(type: string, props: Props): boolean { export function isTextChild(type: string, props: Props): boolean {
@ -168,7 +168,7 @@ export function submitDomUpdate(tag: string, vNode: VNode) {
updateCommonProp(element, 'checked', newProps.checked, true); updateCommonProp(element, 'checked', newProps.checked, true);
} }
const isNativeTag = isNativeElement(type, newProps); const isNativeTag = isNativeElement(type, newProps);
updateDomProps(element, changeList, isNativeTag); setDomProps(element, changeList, isNativeTag, false);
updateValue(type, element, newProps); updateValue(type, element, newProps);
} }
} }

View File

@ -6,9 +6,23 @@ import { setStyles } from './StyleHandler';
import { import {
listenNonDelegatedEvent listenNonDelegatedEvent
} from '../../event/EventBinding'; } from '../../event/EventBinding';
import { isEventProp, isNativeElement } from '../validators/ValidateProps'; import { isEventProp } from '../validators/ValidateProps';
// 初始化DOM属性和更新 DOM 属性
export function setDomProps(
dom: Element,
props: Object,
isNativeTag: boolean,
isInit: boolean,
): void {
const keysOfProps = Object.keys(props);
let propName;
let propVal;
const keyLength = keysOfProps.length;
for (let i = 0; i < keyLength; i++) {
propName = keysOfProps[i];
propVal = props[propName];
function updateOneProp(dom, propName, isNativeTag, propVal?, isInit?: boolean) {
if (propName === 'style') { if (propName === 'style') {
setStyles(dom, propVal); setStyles(dom, propVal);
} else if (isEventProp(propName)) { } else if (isEventProp(propName)) {
@ -23,50 +37,19 @@ function updateOneProp(dom, propName, isNativeTag, propVal?, isInit?: boolean) {
} }
} else if (propName === 'dangerouslySetInnerHTML') { } else if (propName === 'dangerouslySetInnerHTML') {
dom.innerHTML = propVal.__html; dom.innerHTML = propVal.__html;
} else { } else if (!isInit || (isInit && propVal != null)) {
if (!isInit || (isInit && propVal != null)) {
updateCommonProp(dom, propName, propVal, isNativeTag); updateCommonProp(dom, propName, propVal, isNativeTag);
} }
} }
} }
// 初始化DOM属性
export function setDomProps(
tagName: string,
dom: Element,
props: Object,
): void {
const isNativeTag = isNativeElement(tagName, props);
const keysOfProps = Object.keys(props);
let propName;
let propVal;
const keyLength = keysOfProps.length;
for (let i = 0; i < keyLength; i++) {
propName = keysOfProps[i];
propVal = props[propName];
updateOneProp(dom, propName, isNativeTag, propVal, true);
}
}
// 更新 DOM 属性
export function updateDomProps(
dom: Element,
changeList: Map<string, any>,
isNativeTag: boolean,
): void {
for(const [propName, propVal] of changeList) {
updateOneProp(dom, propName, isNativeTag, propVal);
}
}
// 找出两个 DOM 属性的差别,生成需要更新的属性集合 // 找出两个 DOM 属性的差别,生成需要更新的属性集合
export function compareProps( export function compareProps(
oldProps: Object, oldProps: Object,
newProps: Object, newProps: Object,
): Map<string, any> { ): Object {
let updatesForStyle = {}; let updatesForStyle = {};
const toUpdateProps = new Map(); const toUpdateProps = {};
const keysOfOldProps = Object.keys(oldProps); const keysOfOldProps = Object.keys(oldProps);
const keysOfNewProps = Object.keys(newProps); const keysOfNewProps = Object.keys(newProps);
@ -98,11 +81,11 @@ export function compareProps(
continue; continue;
} else if (isEventProp(propName)) { } else if (isEventProp(propName)) {
if (!allDelegatedHorizonEvents.has(propName)) { if (!allDelegatedHorizonEvents.has(propName)) {
toUpdateProps.set(propName, null); toUpdateProps[propName] = null;
} }
} else { } else {
// 其它属性都要加入到删除队列里面,等待删除 // 其它属性都要加入到删除队列里面,等待删除
toUpdateProps.set(propName, null); toUpdateProps[propName] = null;
} }
} }
@ -144,7 +127,7 @@ export function compareProps(
} }
} else { // 之前未设置 style 属性或者设置了空值 } else { // 之前未设置 style 属性或者设置了空值
if (Object.keys(updatesForStyle).length === 0) { if (Object.keys(updatesForStyle).length === 0) {
toUpdateProps.set(propName, null); toUpdateProps[propName] = null;
} }
updatesForStyle = newPropValue; updatesForStyle = newPropValue;
} }
@ -153,25 +136,25 @@ export function compareProps(
oldHTML = oldPropValue ? oldPropValue.__html : undefined; oldHTML = oldPropValue ? oldPropValue.__html : undefined;
if (newHTML != null) { if (newHTML != null) {
if (oldHTML !== newHTML) { if (oldHTML !== newHTML) {
toUpdateProps.set(propName, newPropValue); toUpdateProps[propName] = newPropValue;
} }
} }
} else if (propName === 'children') { } else if (propName === 'children') {
if (typeof newPropValue === 'string' || typeof newPropValue === 'number') { if (typeof newPropValue === 'string' || typeof newPropValue === 'number') {
toUpdateProps.set(propName, String(newPropValue)); toUpdateProps[propName] = String(newPropValue);
} }
} else if (isEventProp(propName)) { } else if (isEventProp(propName)) {
if (!allDelegatedHorizonEvents.has(propName)) { if (!allDelegatedHorizonEvents.has(propName)) {
toUpdateProps.set(propName, newPropValue); toUpdateProps[propName] = newPropValue;
} }
} else { } else {
toUpdateProps.set(propName, newPropValue); toUpdateProps[propName] = newPropValue;
} }
} }
// 处理style // 处理style
if (Object.keys(updatesForStyle).length > 0) { if (Object.keys(updatesForStyle).length > 0) {
toUpdateProps.set('style', updatesForStyle); toUpdateProps['style'] = updatesForStyle;
} }
return toUpdateProps; return toUpdateProps;

View File

@ -10,7 +10,7 @@ import {
import { getListeners as getChangeListeners } from './simulatedEvtHandler/ChangeEventHandler'; import { getListeners as getChangeListeners } from './simulatedEvtHandler/ChangeEventHandler';
import { getListeners as getSelectionListeners } from './simulatedEvtHandler/SelectionEventHandler'; import { getListeners as getSelectionListeners } from './simulatedEvtHandler/SelectionEventHandler';
import { import {
addOnPrefix, setPropertyWritable, setPropertyWritable,
} from './utils'; } from './utils';
import { decorateNativeEvent } from './customEvents/EventFactory'; import { decorateNativeEvent } from './customEvents/EventFactory';
import { getListenersFromTree } from './ListenerGetter'; import { getListenersFromTree } from './ListenerGetter';
@ -27,7 +27,9 @@ function getCommonListeners(
target: null | EventTarget, target: null | EventTarget,
isCapture: boolean, isCapture: boolean,
): ListenerUnitList { ): ListenerUnitList {
const horizonEvtName = addOnPrefix(CommonEventToHorizonMap[nativeEvtName]); const name = CommonEventToHorizonMap[nativeEvtName];
const horizonEvtName = !name ? '' : `on${name[0].toUpperCase()}${name.slice(1)}`; // 例dragEnd -> onDragEnd
if (!horizonEvtName) { if (!horizonEvtName) {
return []; return [];
} }

View File

@ -6,15 +6,6 @@ export function isInputElement(dom?: HTMLElement): boolean {
return false; return false;
} }
// 例dragEnd -> onDragEnd
export function addOnPrefix(name) {
if (!name) {
return '';
}
return 'on' + name[0].toUpperCase() + name.slice(1);
}
export function setPropertyWritable(obj, propName) { export function setPropertyWritable(obj, propName) {
const desc = Object.getOwnPropertyDescriptor(obj, propName); const desc = Object.getOwnPropertyDescriptor(obj, propName);
if (!desc || !desc.writable) { if (!desc || !desc.writable) {

View File

@ -59,11 +59,11 @@ function collectDirtyNodes(vNode: VNode, parent: VNode): void {
const dirtyNodes = vNode.dirtyNodes; const dirtyNodes = vNode.dirtyNodes;
if (dirtyNodes !== null && dirtyNodes.length) { if (dirtyNodes !== null && dirtyNodes.length) {
if (parent.dirtyNodes === null) { if (parent.dirtyNodes === null) {
parent.dirtyNodes = [...vNode.dirtyNodes]; parent.dirtyNodes = dirtyNodes;
} else { } else {
parent.dirtyNodes.push(...vNode.dirtyNodes); parent.dirtyNodes.push(...vNode.dirtyNodes);
}
dirtyNodes.length = 0; dirtyNodes.length = 0;
}
vNode.dirtyNodes = null; vNode.dirtyNodes = null;
} }
@ -236,7 +236,7 @@ function buildVNodeTree(treeRoot: VNode) {
// 当在componentWillUnmount中调用setStateparent可能是null因为startVNode会被clear // 当在componentWillUnmount中调用setStateparent可能是null因为startVNode会被clear
if (parent !== null) { if (parent !== null) {
resetNamespaceCtx(parent); resetNamespaceCtx(parent);
setNamespaceCtx(parent, parent.outerDom); setNamespaceCtx(parent, parent.realNode);
} }
// 恢复父节点的context // 恢复父节点的context

View File

@ -39,7 +39,7 @@ export type ContextType<T> = {
export type PortalType = { export type PortalType = {
vtype: number; vtype: number;
key: null | string; key: null | string;
outerDom: any; realNode: any;
children: any; children: any;
}; };

View File

@ -18,11 +18,6 @@ export enum UpdateState {
Error = 'Error', Error = 'Error',
} }
// 初始化更新数组
export function createUpdateArray(vNode: VNode): void {
vNode.updates = []; // 新产生的update会加入这个数组
}
// 创建update对象 // 创建update对象
export function newUpdate(): Update { export function newUpdate(): Update {
return { return {
@ -35,8 +30,11 @@ export function newUpdate(): Update {
// 将update对象加入updates // 将update对象加入updates
export function pushUpdate(vNode: VNode, update: Update) { export function pushUpdate(vNode: VNode, update: Update) {
const updates = vNode.updates; const updates = vNode.updates;
if (updates !== null) {
updates?.push(update); updates.push(update);
} else {
vNode.updates = [update];
}
} }
// 根据update获取新的state // 根据update获取新的state
@ -98,14 +96,16 @@ export function processUpdates(vNode: VNode, inst: any, props: any): void {
const updates: Updates = vNode.updates; const updates: Updates = vNode.updates;
vNode.isForceUpdate = false; vNode.isForceUpdate = false;
if (updates !== null) {
const toProcessUpdates = [...updates]; const toProcessUpdates = [...updates];
updates.length = 0; updates.length = 0;
if (toProcessUpdates.length) { if (toProcessUpdates.length) {
calcUpdates(vNode, props, inst, toProcessUpdates); calcUpdates(vNode, props, inst, toProcessUpdates);
} }
} }
}
export function pushForceUpdate(vNode: VNode) { export function pushForceUpdate(vNode: VNode) {
const update = newUpdate(); const update = newUpdate();
update.type = UpdateState.ForceUpdate; update.type = UpdateState.ForceUpdate;

View File

@ -3,13 +3,13 @@ import type {PortalType} from '../Types';
export function createPortal( export function createPortal(
children: any, children: any,
outerDom: any, realNode: any,
key: string = '', key: string = '',
): PortalType { ): PortalType {
return { return {
vtype: TYPE_PORTAL, vtype: TYPE_PORTAL,
key: key == '' ? '' : '' + key, key: key == '' ? '' : '' + key,
children, children,
outerDom, realNode,
}; };
} }

View File

@ -153,7 +153,7 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
} }
break; break;
} else if (newChild.vtype === TYPE_PORTAL) { } else if (newChild.vtype === TYPE_PORTAL) {
if (oldNode === null || oldNode.tag !== DomPortal || oldNode.outerDom !== newChild.outerDom) { if (oldNode === null || oldNode.tag !== DomPortal || oldNode.realNode !== newChild.realNode) {
resultNode = createPortalVNode(newChild); resultNode = createPortalVNode(newChild);
} else { } else {
resultNode = updateVNode(oldNode, newChild.children || []); resultNode = updateVNode(oldNode, newChild.children || []);
@ -578,7 +578,7 @@ function diffObjectNodeHandler(
} else if (newChild.vtype === TYPE_PORTAL) { } else if (newChild.vtype === TYPE_PORTAL) {
if (canReuseNode) { if (canReuseNode) {
// 可以复用 // 可以复用
if (canReuseNode.tag === DomPortal && canReuseNode.outerDom === newChild.outerDom) { if (canReuseNode.tag === DomPortal && canReuseNode.realNode === newChild.realNode) {
resultNode = updateVNode(canReuseNode, newChild.children || []); resultNode = updateVNode(canReuseNode, newChild.children || []);
startDelVNode = canReuseNode.next; startDelVNode = canReuseNode.next;
resultNode.next = null; resultNode.next = null;

View File

@ -18,7 +18,7 @@ import componentRenders from './index';
function handlerContext(processing: VNode) { function handlerContext(processing: VNode) {
switch (processing.tag) { switch (processing.tag) {
case TreeRoot: case TreeRoot:
setNamespaceCtx(processing, processing.outerDom); setNamespaceCtx(processing, processing.realNode);
break; break;
case DomComponent: case DomComponent:
setNamespaceCtx(processing); setNamespaceCtx(processing);
@ -29,7 +29,7 @@ function handlerContext(processing: VNode) {
break; break;
} }
case DomPortal: case DomPortal:
setNamespaceCtx(processing, processing.outerDom); setNamespaceCtx(processing, processing.realNode);
break; break;
case ContextProvider: { case ContextProvider: {
const newValue = processing.props.value; const newValue = processing.props.value;

View File

@ -23,7 +23,6 @@ import {
import { FlagUtils, DidCapture } from '../vnode/VNodeFlags'; import { FlagUtils, DidCapture } from '../vnode/VNodeFlags';
import { markRef } from './BaseComponent'; import { markRef } from './BaseComponent';
import { import {
createUpdateArray,
processUpdates, processUpdates,
} from '../UpdateHandler'; } from '../UpdateHandler';
import { getContextChangeCtx, setContextChangeCtx } from '../ContextSaver'; import { getContextChangeCtx, setContextChangeCtx } from '../ContextSaver';
@ -47,15 +46,13 @@ function mountInstance(clazz, processing: VNode, nextProps: object) {
} }
// 构造实例 // 构造实例
callConstructor(processing, clazz, nextProps); const inst = callConstructor(processing, clazz, nextProps);
const inst = processing.realNode;
inst.props = nextProps; inst.props = nextProps;
inst.state = processing.state; inst.state = processing.state;
inst.context = getCurrentContext(clazz, processing); inst.context = getCurrentContext(clazz, processing);
inst.refs = {}; inst.refs = {};
createUpdateArray(processing);
processUpdates(processing, inst, nextProps); processUpdates(processing, inst, nextProps);
inst.state = processing.state; inst.state = processing.state;
@ -106,7 +103,15 @@ function markLifeCycle(processing: VNode, nextProps: object, shouldUpdate: Boole
} }
// 用于类组件 // 用于类组件
export function captureClassComponent(processing: VNode, clazz: any, nextProps: object): VNode | null { export function captureRender(processing: VNode): VNode | null {
let clazz = processing.type;
let nextProps = processing.props;
if (processing.isLazyComponent) {
nextProps = mergeDefaultProps(clazz, nextProps);
if (processing.promiseResolve) { // 该函数被 lazy 组件使用,未加载的组件需要加载组件的真实内容
clazz = clazz._load(clazz._content);
}
}
const isOldCxtExist = isOldProvider(clazz); const isOldCxtExist = isOldProvider(clazz);
cacheOldCtx(processing, isOldCxtExist); cacheOldCtx(processing, isOldCxtExist);
@ -123,18 +128,13 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps:
const newContext = getCurrentContext(clazz, processing); const newContext = getCurrentContext(clazz, processing);
// 子节点抛出异常时如果本class是个捕获异常的处理节点这时候oldProps是null所以需要使用props // 子节点抛出异常时如果本class是个捕获异常的处理节点这时候oldProps是null所以需要使用props
let oldProps = (processing.flags & DidCapture) === DidCapture ? processing.props : processing.oldProps; const oldProps = (processing.flags & DidCapture) === DidCapture ? processing.props : processing.oldProps;
if (processing.isLazyComponent) {
oldProps = mergeDefaultProps(processing.type, oldProps);
}
inst.props = oldProps;
if (oldProps !== processing.props || inst.context !== newContext) { if (oldProps !== processing.props || inst.context !== newContext) {
// 在已挂载的组件接收新的 props 之前被调用 // 在已挂载的组件接收新的 props 之前被调用
callComponentWillReceiveProps(inst, nextProps, newContext); callComponentWillReceiveProps(inst, nextProps, newContext);
} }
inst.state = processing.state;
processUpdates(processing, inst, nextProps); processUpdates(processing, inst, nextProps);
// 如果 props, state, context 都没有变化且 isForceUpdate 为 false则不需要更新 // 如果 props, state, context 都没有变化且 isForceUpdate 为 false则不需要更新
@ -183,13 +183,6 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps:
} }
} }
export function captureRender(processing: VNode): VNode | null {
const clazz = processing.type;
const props = processing.props;
const nextProps = processing.isLazyComponent ? mergeDefaultProps(clazz, props) : props;
return captureClassComponent(processing, clazz, nextProps);
}
export function bubbleRender(processing: VNode) { export function bubbleRender(processing: VNode) {
if (isOldProvider(processing.type)) { if (isOldProvider(processing.type)) {
resetOldCtx(processing); resetOldCtx(processing);

View File

@ -38,14 +38,15 @@ function updateDom(
oldProps, oldProps,
newProps, newProps,
); );
processing.changeList = changeList;
// 输入类型的直接标记更新 // 输入类型的直接标记更新
if (type === 'input' || type === 'textarea' || type === 'select' || type === 'option') { if (type === 'input' || type === 'textarea' || type === 'select' || type === 'option') {
FlagUtils.markUpdate(processing); FlagUtils.markUpdate(processing);
processing.changeList = changeList;
} else { } else {
// 其它的类型,数据有变化才标记更新 // 其它的类型,数据有变化才标记更新
if (changeList.size) { if (Object.keys(changeList).length) {
processing.changeList = changeList;
FlagUtils.markUpdate(processing); FlagUtils.markUpdate(processing);
} }
} }
@ -105,7 +106,7 @@ export function bubbleRender(processing: VNode) {
} }
} }
function captureDomComponent(processing: VNode): VNode | null { export function captureRender(processing: VNode): VNode | null {
setNamespaceCtx(processing); setNamespaceCtx(processing);
const type = processing.type; const type = processing.type;
@ -127,7 +128,3 @@ function captureDomComponent(processing: VNode): VNode | null {
processing.child = createChildrenByDiff(processing, processing.child, nextChildren, !processing.isCreated); processing.child = createChildrenByDiff(processing, processing.child, nextChildren, !processing.isCreated);
return processing.child; return processing.child;
} }
export function captureRender(processing: VNode): VNode | null {
return captureDomComponent(processing);
}

View File

@ -7,12 +7,12 @@ export function bubbleRender(processing: VNode) {
resetNamespaceCtx(processing); resetNamespaceCtx(processing);
if (processing.isCreated) { if (processing.isCreated) {
prePortal(processing.outerDom); prePortal(processing.realNode);
} }
} }
function capturePortalComponent(processing: VNode) { function capturePortalComponent(processing: VNode) {
setNamespaceCtx(processing, processing.outerDom); setNamespaceCtx(processing, processing.realNode);
const newElements = processing.props; const newElements = processing.props;
if (processing.isCreated) { if (processing.isCreated) {

View File

@ -10,7 +10,7 @@ import {
} from '../vnode/VNodeTags'; } from '../vnode/VNodeTags';
import { throwIfTrue } from '../utils/throwIfTrue'; import { throwIfTrue } from '../utils/throwIfTrue';
import { captureFunctionComponent } from './FunctionComponent'; import { captureFunctionComponent } from './FunctionComponent';
import { captureClassComponent } from './ClassComponent'; import { captureRender as captureClassComponent } from './ClassComponent';
import { captureMemoComponent } from './MemoComponent'; import { captureMemoComponent } from './MemoComponent';
export function bubbleRender() { } export function bubbleRender() { }

View File

@ -12,7 +12,7 @@ export function bubbleRender(processing: VNode) {
} }
function updateTreeRoot(processing) { function updateTreeRoot(processing) {
setNamespaceCtx(processing, processing.outerDom); setNamespaceCtx(processing, processing.realNode);
const updates = processing.updates; const updates = processing.updates;
throwIfTrue( throwIfTrue(

View File

@ -118,17 +118,21 @@ export function callComponentWillUpdate(inst, newProps, newState, nextContext) {
} }
export function callComponentWillReceiveProps(inst, newProps: object, newContext: object) { export function callComponentWillReceiveProps(inst, newProps: object, newContext: object) {
const oldState = inst.state;
if (inst.componentWillReceiveProps) { if (inst.componentWillReceiveProps) {
const oldState = inst.state;
inst.componentWillReceiveProps(newProps, newContext); inst.componentWillReceiveProps(newProps, newContext);
}
if (inst.UNSAFE_componentWillReceiveProps) {
inst.UNSAFE_componentWillReceiveProps(newProps, newContext);
}
if (inst.state !== oldState) { if (inst.state !== oldState) {
changeStateContent.call(inst, UpdateState.Override, inst.state, null); changeStateContent.call(inst, UpdateState.Override, inst.state, null);
} }
} }
if (inst.UNSAFE_componentWillReceiveProps) {
const oldState = inst.state;
inst.UNSAFE_componentWillReceiveProps(newProps, newContext);
if (inst.state !== oldState) {
changeStateContent.call(inst, UpdateState.Override, inst.state, null);
}
}
}
export function markComponentDidMount(processing: VNode) { export function markComponentDidMount(processing: VNode) {
const inst = processing.realNode; const inst = processing.realNode;

View File

@ -225,12 +225,9 @@ function submitAddition(vNode: VNode): void {
let tag; let tag;
while (parent !== null) { while (parent !== null) {
tag = parent.tag; tag = parent.tag;
if (tag === DomComponent) { if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) {
parentDom = parent.realNode; parentDom = parent.realNode;
break; break;
} else if (tag === TreeRoot || tag === DomPortal) {
parentDom = parent.outerDom;
break;
} }
parent = parent.parent; parent = parent.parent;
} }
@ -292,12 +289,9 @@ function unmountDomComponents(vNode: VNode): void {
let tag; let tag;
while (parent !== null) { while (parent !== null) {
tag = parent.tag; tag = parent.tag;
if (tag === DomComponent) { if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) {
currentParent = parent.realNode; currentParent = parent.realNode;
break; break;
} else if (tag === TreeRoot || tag === DomPortal) {
currentParent = parent.outerDom;
break;
} }
parent = parent.parent; parent = parent.parent;
} }
@ -312,7 +306,7 @@ function unmountDomComponents(vNode: VNode): void {
removeChildDom(currentParent, node.realNode); removeChildDom(currentParent, node.realNode);
} else if (node.tag === DomPortal) { } else if (node.tag === DomPortal) {
if (node.child !== null) { if (node.child !== null) {
currentParent = node.outerDom; currentParent = node.realNode;
} }
} else { } else {
unmountVNode(node); unmountVNode(node);
@ -349,12 +343,9 @@ function submitClear(vNode: VNode): void {
let tag; let tag;
while (parent !== null) { while (parent !== null) {
tag = parent.tag; tag = parent.tag;
if (tag === DomComponent) { if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) {
parentDom = parent.realNode; parentDom = parent.realNode;
break; break;
} else if (tag === TreeRoot || tag === DomPortal) {
parentDom = parent.outerDom;
break;
} }
parent = parent.parent; parent = parent.parent;
} }

View File

@ -39,7 +39,6 @@ export class VNode {
dirtyNodes: Array<VNode> | null = null; // 需要改动的节点数组 dirtyNodes: Array<VNode> | null = null; // 需要改动的节点数组
shouldUpdate: boolean = false; shouldUpdate: boolean = false;
childShouldUpdate: boolean = false; childShouldUpdate: boolean = false;
outerDom: any;
task: any; task: any;
// 使用这个变量来记录修改前的值,用于恢复。 // 使用这个变量来记录修改前的值,用于恢复。
@ -67,7 +66,7 @@ export class VNode {
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode处理ref的时候使用 belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode处理ref的时候使用
constructor(tag: VNodeTag, props: any, key: null | string, outerDom) { constructor(tag: VNodeTag, props: any, key: null | string, realNode) {
this.tag = tag; // 对应组件的类型比如ClassComponent等 this.tag = tag; // 对应组件的类型比如ClassComponent等
this.key = key; this.key = key;
@ -75,10 +74,9 @@ export class VNode {
switch (tag) { switch (tag) {
case TreeRoot: case TreeRoot:
this.outerDom = outerDom; this.realNode = realNode;
this.task = null; this.task = null;
this.toUpdateNodes = new Set<VNode>(); this.toUpdateNodes = new Set<VNode>();
this.realNode = null;
this.updates = null; this.updates = null;
this.stateCallbacks = null; this.stateCallbacks = null;
this.state = null; this.state = null;
@ -138,6 +136,7 @@ export class VNode {
this.stateCallbacks = null; this.stateCallbacks = null;
this.isLazyComponent = true; this.isLazyComponent = true;
this.lazyType = null; this.lazyType = null;
this.updates = null;
break; break;
case Fragment: case Fragment:
break; break;

View File

@ -16,7 +16,6 @@ import {
MemoComponent, MemoComponent,
SuspenseComponent, SuspenseComponent,
} from './VNodeTags'; } from './VNodeTags';
import { createUpdateArray } from '../UpdateHandler';
import { import {
TYPE_CONTEXT, TYPE_CONTEXT,
TYPE_FORWARD_REF, TYPE_FRAGMENT, TYPE_FORWARD_REF, TYPE_FRAGMENT,
@ -39,8 +38,8 @@ const typeMap = {
[TYPE_LAZY]: LazyComponent, [TYPE_LAZY]: LazyComponent,
}; };
const newVirtualNode = function(tag: VNodeTag, key?: null | string, vNodeProps?: any, outerDom?: any): VNode { const newVirtualNode = function(tag: VNodeTag, key?: null | string, vNodeProps?: any, realNode?: any): VNode {
return new VNode(tag, vNodeProps, key, outerDom); return new VNode(tag, vNodeProps, key, realNode);
}; };
function isClassComponent(comp: Function) { function isClassComponent(comp: Function) {
@ -100,7 +99,7 @@ export function createPortalVNode(portal) {
const children = portal.children ?? []; const children = portal.children ?? [];
const vNode = newVirtualNode(DomPortal, portal.key, children); const vNode = newVirtualNode(DomPortal, portal.key, children);
vNode.shouldUpdate = true; vNode.shouldUpdate = true;
vNode.outerDom = portal.outerDom; vNode.realNode = portal.realNode;
return vNode; return vNode;
} }
@ -137,7 +136,7 @@ export function createUndeterminedVNode(type, key, props) {
export function createTreeRootVNode(container) { export function createTreeRootVNode(container) {
const vNode = newVirtualNode(TreeRoot, null, null, container); const vNode = newVirtualNode(TreeRoot, null, null, container);
vNode.path += 0; vNode.path += 0;
createUpdateArray(vNode); vNode.updates = [];
return vNode; return vNode;
} }
@ -150,7 +149,7 @@ export function createVNode(tag: VNodeTag | string, ...secondArg) {
vNode = newVirtualNode(TreeRoot, null, null, secondArg[0]); vNode = newVirtualNode(TreeRoot, null, null, secondArg[0]);
vNode.path += 0; vNode.path += 0;
createUpdateArray(vNode); vNode.updates = [];
break; break;
} }

View File

@ -24,12 +24,10 @@ const LifecycleEffectArr = Update | Callback | Ref | Snapshot;
export class FlagUtils { export class FlagUtils {
static removeFlag(node: VNode, flag: number) { static removeFlag(node: VNode, flag: number) {
const flags = node.flags; node.flags &= ~flag;
node.flags = flags & (~flag);
} }
static removeLifecycleEffectFlags(node) { static removeLifecycleEffectFlags(node) {
const flags = node.flags; node.flags &= ~LifecycleEffectArr;
node.flags = flags & (~LifecycleEffectArr);
} }
static hasAnyFlag(node: VNode) { // 有标志位 static hasAnyFlag(node: VNode) { // 有标志位
return node.flags !== InitFlag; return node.flags !== InitFlag;

View File

@ -210,7 +210,7 @@ function isPortalRoot(vNode, targetContainer) {
while (topVNode !== null) { while (topVNode !== null) {
const grandTag = topVNode.tag; const grandTag = topVNode.tag;
if (grandTag === TreeRoot || grandTag === DomPortal) { if (grandTag === TreeRoot || grandTag === DomPortal) {
const topContainer = topVNode.outerDom; const topContainer = topVNode.realNode;
// 如果topContainer是targetContainer不需要在这里处理 // 如果topContainer是targetContainer不需要在这里处理
if (isSameContainer(topContainer, targetContainer)) { if (isSameContainer(topContainer, targetContainer)) {
return true; return true;
@ -229,7 +229,7 @@ export function getExactNode(targetVNode, targetContainer) {
let vNode = targetVNode; let vNode = targetVNode;
while (vNode !== null) { while (vNode !== null) {
if (vNode.tag === TreeRoot || vNode.tag === DomPortal) { if (vNode.tag === TreeRoot || vNode.tag === DomPortal) {
let container = vNode.outerDom; let container = vNode.realNode;
if (isSameContainer(container, targetContainer)) { if (isSameContainer(container, targetContainer)) {
break; break;
} }