Match-id-70d03a8fc008ccce49a3f8517fc56c3d6ecbcf98
This commit is contained in:
commit
a1c73a6e2f
|
@ -19,7 +19,7 @@ import {
|
|||
} from './valueHandler';
|
||||
import {
|
||||
compareProps,
|
||||
setDomProps, updateDomProps
|
||||
setDomProps,
|
||||
} from './DOMPropertiesHandler/DOMPropertiesHandler';
|
||||
import { isNativeElement, validateProps } from './validators/ValidateProps';
|
||||
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);
|
||||
|
||||
// 初始化DOM属性(不包括value,defaultValue)
|
||||
setDomProps(tagName, dom, props);
|
||||
const isNativeTag = isNativeElement(tagName, props);
|
||||
setDomProps(dom, props, isNativeTag, true);
|
||||
|
||||
if (tagName === 'input' || tagName === 'textarea') {
|
||||
// 增加监听value和checked的set、get方法
|
||||
|
@ -110,7 +111,7 @@ export function getPropChangeList(
|
|||
type: string,
|
||||
lastRawProps: Props,
|
||||
nextRawProps: Props,
|
||||
): Map<string, any> {
|
||||
): Object {
|
||||
// 校验两个对象的不同
|
||||
validateProps(type, nextRawProps);
|
||||
|
||||
|
@ -118,8 +119,7 @@ export function getPropChangeList(
|
|||
const oldProps: Object = getPropsWithoutValue(type, dom, lastRawProps);
|
||||
const newProps: Object = getPropsWithoutValue(type, dom, nextRawProps);
|
||||
|
||||
const changeList = compareProps(oldProps, newProps);
|
||||
return changeList;
|
||||
return compareProps(oldProps, newProps);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
const isNativeTag = isNativeElement(type, newProps);
|
||||
updateDomProps(element, changeList, isNativeTag);
|
||||
setDomProps(element, changeList, isNativeTag, false);
|
||||
updateValue(type, element, newProps);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,37 +6,15 @@ import { setStyles } from './StyleHandler';
|
|||
import {
|
||||
listenNonDelegatedEvent
|
||||
} from '../../event/EventBinding';
|
||||
import { isEventProp, isNativeElement } from '../validators/ValidateProps';
|
||||
import { isEventProp } from '../validators/ValidateProps';
|
||||
|
||||
function updateOneProp(dom, propName, isNativeTag, propVal?, isInit?: boolean) {
|
||||
if (propName === 'style') {
|
||||
setStyles(dom, propVal);
|
||||
} else if (isEventProp(propName)) {
|
||||
// 事件监听属性处理
|
||||
if (!allDelegatedHorizonEvents.has(propName)) {
|
||||
listenNonDelegatedEvent(propName, dom, propVal);
|
||||
}
|
||||
} else if (propName === 'children') { // 只处理纯文本子节点,其他children在VNode树中处理
|
||||
const type = typeof propVal;
|
||||
if (type === 'string' || type === 'number') {
|
||||
dom.textContent = propVal;
|
||||
}
|
||||
} else if (propName === 'dangerouslySetInnerHTML') {
|
||||
dom.innerHTML = propVal.__html;
|
||||
} else {
|
||||
if (!isInit || (isInit && propVal != null)) {
|
||||
updateCommonProp(dom, propName, propVal, isNativeTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化DOM属性
|
||||
// 初始化DOM属性和更新 DOM 属性
|
||||
export function setDomProps(
|
||||
tagName: string,
|
||||
dom: Element,
|
||||
props: Object,
|
||||
isNativeTag: boolean,
|
||||
isInit: boolean,
|
||||
): void {
|
||||
const isNativeTag = isNativeElement(tagName, props);
|
||||
const keysOfProps = Object.keys(props);
|
||||
let propName;
|
||||
let propVal;
|
||||
|
@ -45,18 +23,23 @@ export function setDomProps(
|
|||
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);
|
||||
if (propName === 'style') {
|
||||
setStyles(dom, propVal);
|
||||
} else if (isEventProp(propName)) {
|
||||
// 事件监听属性处理
|
||||
if (!allDelegatedHorizonEvents.has(propName)) {
|
||||
listenNonDelegatedEvent(propName, dom, propVal);
|
||||
}
|
||||
} else if (propName === 'children') { // 只处理纯文本子节点,其他children在VNode树中处理
|
||||
const type = typeof propVal;
|
||||
if (type === 'string' || type === 'number') {
|
||||
dom.textContent = propVal;
|
||||
}
|
||||
} else if (propName === 'dangerouslySetInnerHTML') {
|
||||
dom.innerHTML = propVal.__html;
|
||||
} else if (!isInit || (isInit && propVal != null)) {
|
||||
updateCommonProp(dom, propName, propVal, isNativeTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,9 +47,9 @@ export function updateDomProps(
|
|||
export function compareProps(
|
||||
oldProps: Object,
|
||||
newProps: Object,
|
||||
): Map<string, any> {
|
||||
): Object {
|
||||
let updatesForStyle = {};
|
||||
const toUpdateProps = new Map();
|
||||
const toUpdateProps = {};
|
||||
const keysOfOldProps = Object.keys(oldProps);
|
||||
const keysOfNewProps = Object.keys(newProps);
|
||||
|
||||
|
@ -98,11 +81,11 @@ export function compareProps(
|
|||
continue;
|
||||
} else if (isEventProp(propName)) {
|
||||
if (!allDelegatedHorizonEvents.has(propName)) {
|
||||
toUpdateProps.set(propName, null);
|
||||
toUpdateProps[propName] = null;
|
||||
}
|
||||
} else {
|
||||
// 其它属性都要加入到删除队列里面,等待删除
|
||||
toUpdateProps.set(propName, null);
|
||||
toUpdateProps[propName] = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,7 +127,7 @@ export function compareProps(
|
|||
}
|
||||
} else { // 之前未设置 style 属性或者设置了空值
|
||||
if (Object.keys(updatesForStyle).length === 0) {
|
||||
toUpdateProps.set(propName, null);
|
||||
toUpdateProps[propName] = null;
|
||||
}
|
||||
updatesForStyle = newPropValue;
|
||||
}
|
||||
|
@ -153,25 +136,25 @@ export function compareProps(
|
|||
oldHTML = oldPropValue ? oldPropValue.__html : undefined;
|
||||
if (newHTML != null) {
|
||||
if (oldHTML !== newHTML) {
|
||||
toUpdateProps.set(propName, newPropValue);
|
||||
toUpdateProps[propName] = newPropValue;
|
||||
}
|
||||
}
|
||||
} else if (propName === 'children') {
|
||||
if (typeof newPropValue === 'string' || typeof newPropValue === 'number') {
|
||||
toUpdateProps.set(propName, String(newPropValue));
|
||||
toUpdateProps[propName] = String(newPropValue);
|
||||
}
|
||||
} else if (isEventProp(propName)) {
|
||||
if (!allDelegatedHorizonEvents.has(propName)) {
|
||||
toUpdateProps.set(propName, newPropValue);
|
||||
toUpdateProps[propName] = newPropValue;
|
||||
}
|
||||
} else {
|
||||
toUpdateProps.set(propName, newPropValue);
|
||||
toUpdateProps[propName] = newPropValue;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理style
|
||||
if (Object.keys(updatesForStyle).length > 0) {
|
||||
toUpdateProps.set('style', updatesForStyle);
|
||||
toUpdateProps['style'] = updatesForStyle;
|
||||
}
|
||||
|
||||
return toUpdateProps;
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
import { getListeners as getChangeListeners } from './simulatedEvtHandler/ChangeEventHandler';
|
||||
import { getListeners as getSelectionListeners } from './simulatedEvtHandler/SelectionEventHandler';
|
||||
import {
|
||||
addOnPrefix, setPropertyWritable,
|
||||
setPropertyWritable,
|
||||
} from './utils';
|
||||
import { decorateNativeEvent } from './customEvents/EventFactory';
|
||||
import { getListenersFromTree } from './ListenerGetter';
|
||||
|
@ -27,7 +27,9 @@ function getCommonListeners(
|
|||
target: null | EventTarget,
|
||||
isCapture: boolean,
|
||||
): ListenerUnitList {
|
||||
const horizonEvtName = addOnPrefix(CommonEventToHorizonMap[nativeEvtName]);
|
||||
const name = CommonEventToHorizonMap[nativeEvtName];
|
||||
const horizonEvtName = !name ? '' : `on${name[0].toUpperCase()}${name.slice(1)}`; // 例:dragEnd -> onDragEnd
|
||||
|
||||
if (!horizonEvtName) {
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -6,15 +6,6 @@ export function isInputElement(dom?: HTMLElement): boolean {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 例:dragEnd -> onDragEnd
|
||||
export function addOnPrefix(name) {
|
||||
if (!name) {
|
||||
return '';
|
||||
}
|
||||
return 'on' + name[0].toUpperCase() + name.slice(1);
|
||||
}
|
||||
|
||||
export function setPropertyWritable(obj, propName) {
|
||||
const desc = Object.getOwnPropertyDescriptor(obj, propName);
|
||||
if (!desc || !desc.writable) {
|
||||
|
|
|
@ -59,11 +59,11 @@ function collectDirtyNodes(vNode: VNode, parent: VNode): void {
|
|||
const dirtyNodes = vNode.dirtyNodes;
|
||||
if (dirtyNodes !== null && dirtyNodes.length) {
|
||||
if (parent.dirtyNodes === null) {
|
||||
parent.dirtyNodes = [...vNode.dirtyNodes];
|
||||
parent.dirtyNodes = dirtyNodes;
|
||||
} else {
|
||||
parent.dirtyNodes.push(...vNode.dirtyNodes);
|
||||
dirtyNodes.length = 0;
|
||||
}
|
||||
dirtyNodes.length = 0;
|
||||
vNode.dirtyNodes = null;
|
||||
}
|
||||
|
||||
|
@ -236,7 +236,7 @@ function buildVNodeTree(treeRoot: VNode) {
|
|||
// 当在componentWillUnmount中调用setState,parent可能是null,因为startVNode会被clear
|
||||
if (parent !== null) {
|
||||
resetNamespaceCtx(parent);
|
||||
setNamespaceCtx(parent, parent.outerDom);
|
||||
setNamespaceCtx(parent, parent.realNode);
|
||||
}
|
||||
|
||||
// 恢复父节点的context
|
||||
|
|
|
@ -39,7 +39,7 @@ export type ContextType<T> = {
|
|||
export type PortalType = {
|
||||
vtype: number;
|
||||
key: null | string;
|
||||
outerDom: any;
|
||||
realNode: any;
|
||||
children: any;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,11 +18,6 @@ export enum UpdateState {
|
|||
Error = 'Error',
|
||||
}
|
||||
|
||||
// 初始化更新数组
|
||||
export function createUpdateArray(vNode: VNode): void {
|
||||
vNode.updates = []; // 新产生的update会加入这个数组
|
||||
}
|
||||
|
||||
// 创建update对象
|
||||
export function newUpdate(): Update {
|
||||
return {
|
||||
|
@ -35,8 +30,11 @@ export function newUpdate(): Update {
|
|||
// 将update对象加入updates
|
||||
export function pushUpdate(vNode: VNode, update: Update) {
|
||||
const updates = vNode.updates;
|
||||
|
||||
updates?.push(update);
|
||||
if (updates !== null) {
|
||||
updates.push(update);
|
||||
} else {
|
||||
vNode.updates = [update];
|
||||
}
|
||||
}
|
||||
|
||||
// 根据update获取新的state
|
||||
|
@ -98,12 +96,14 @@ export function processUpdates(vNode: VNode, inst: any, props: any): void {
|
|||
const updates: Updates = vNode.updates;
|
||||
vNode.isForceUpdate = false;
|
||||
|
||||
const toProcessUpdates = [...updates];
|
||||
updates.length = 0;
|
||||
|
||||
if (toProcessUpdates.length) {
|
||||
calcUpdates(vNode, props, inst, toProcessUpdates);
|
||||
if (updates !== null) {
|
||||
const toProcessUpdates = [...updates];
|
||||
updates.length = 0;
|
||||
if (toProcessUpdates.length) {
|
||||
calcUpdates(vNode, props, inst, toProcessUpdates);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function pushForceUpdate(vNode: VNode) {
|
||||
|
|
|
@ -3,13 +3,13 @@ import type {PortalType} from '../Types';
|
|||
|
||||
export function createPortal(
|
||||
children: any,
|
||||
outerDom: any,
|
||||
realNode: any,
|
||||
key: string = '',
|
||||
): PortalType {
|
||||
return {
|
||||
vtype: TYPE_PORTAL,
|
||||
key: key == '' ? '' : '' + key,
|
||||
children,
|
||||
outerDom,
|
||||
realNode,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
|||
}
|
||||
break;
|
||||
} 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);
|
||||
} else {
|
||||
resultNode = updateVNode(oldNode, newChild.children || []);
|
||||
|
@ -578,7 +578,7 @@ function diffObjectNodeHandler(
|
|||
} else if (newChild.vtype === TYPE_PORTAL) {
|
||||
if (canReuseNode) {
|
||||
// 可以复用
|
||||
if (canReuseNode.tag === DomPortal && canReuseNode.outerDom === newChild.outerDom) {
|
||||
if (canReuseNode.tag === DomPortal && canReuseNode.realNode === newChild.realNode) {
|
||||
resultNode = updateVNode(canReuseNode, newChild.children || []);
|
||||
startDelVNode = canReuseNode.next;
|
||||
resultNode.next = null;
|
||||
|
|
|
@ -18,7 +18,7 @@ import componentRenders from './index';
|
|||
function handlerContext(processing: VNode) {
|
||||
switch (processing.tag) {
|
||||
case TreeRoot:
|
||||
setNamespaceCtx(processing, processing.outerDom);
|
||||
setNamespaceCtx(processing, processing.realNode);
|
||||
break;
|
||||
case DomComponent:
|
||||
setNamespaceCtx(processing);
|
||||
|
@ -29,7 +29,7 @@ function handlerContext(processing: VNode) {
|
|||
break;
|
||||
}
|
||||
case DomPortal:
|
||||
setNamespaceCtx(processing, processing.outerDom);
|
||||
setNamespaceCtx(processing, processing.realNode);
|
||||
break;
|
||||
case ContextProvider: {
|
||||
const newValue = processing.props.value;
|
||||
|
|
|
@ -23,7 +23,6 @@ import {
|
|||
import { FlagUtils, DidCapture } from '../vnode/VNodeFlags';
|
||||
import { markRef } from './BaseComponent';
|
||||
import {
|
||||
createUpdateArray,
|
||||
processUpdates,
|
||||
} from '../UpdateHandler';
|
||||
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.state = processing.state;
|
||||
inst.context = getCurrentContext(clazz, processing);
|
||||
inst.refs = {};
|
||||
|
||||
createUpdateArray(processing);
|
||||
processUpdates(processing, inst, nextProps);
|
||||
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);
|
||||
cacheOldCtx(processing, isOldCxtExist);
|
||||
|
||||
|
@ -123,18 +128,13 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps:
|
|||
const newContext = getCurrentContext(clazz, processing);
|
||||
|
||||
// 子节点抛出异常时,如果本class是个捕获异常的处理节点,这时候oldProps是null,所以需要使用props
|
||||
let oldProps = (processing.flags & DidCapture) === DidCapture ? processing.props : processing.oldProps;
|
||||
if (processing.isLazyComponent) {
|
||||
oldProps = mergeDefaultProps(processing.type, oldProps);
|
||||
}
|
||||
inst.props = oldProps;
|
||||
const oldProps = (processing.flags & DidCapture) === DidCapture ? processing.props : processing.oldProps;
|
||||
|
||||
if (oldProps !== processing.props || inst.context !== newContext) {
|
||||
// 在已挂载的组件接收新的 props 之前被调用
|
||||
callComponentWillReceiveProps(inst, nextProps, newContext);
|
||||
}
|
||||
|
||||
inst.state = processing.state;
|
||||
processUpdates(processing, inst, nextProps);
|
||||
|
||||
// 如果 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) {
|
||||
if (isOldProvider(processing.type)) {
|
||||
resetOldCtx(processing);
|
||||
|
|
|
@ -38,14 +38,15 @@ function updateDom(
|
|||
oldProps,
|
||||
newProps,
|
||||
);
|
||||
processing.changeList = changeList;
|
||||
|
||||
// 输入类型的直接标记更新
|
||||
if (type === 'input' || type === 'textarea' || type === 'select' || type === 'option') {
|
||||
FlagUtils.markUpdate(processing);
|
||||
processing.changeList = changeList;
|
||||
} else {
|
||||
// 其它的类型,数据有变化才标记更新
|
||||
if (changeList.size) {
|
||||
if (Object.keys(changeList).length) {
|
||||
processing.changeList = changeList;
|
||||
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);
|
||||
|
||||
const type = processing.type;
|
||||
|
@ -127,7 +128,3 @@ function captureDomComponent(processing: VNode): VNode | null {
|
|||
processing.child = createChildrenByDiff(processing, processing.child, nextChildren, !processing.isCreated);
|
||||
return processing.child;
|
||||
}
|
||||
|
||||
export function captureRender(processing: VNode): VNode | null {
|
||||
return captureDomComponent(processing);
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ export function bubbleRender(processing: VNode) {
|
|||
resetNamespaceCtx(processing);
|
||||
|
||||
if (processing.isCreated) {
|
||||
prePortal(processing.outerDom);
|
||||
prePortal(processing.realNode);
|
||||
}
|
||||
}
|
||||
|
||||
function capturePortalComponent(processing: VNode) {
|
||||
setNamespaceCtx(processing, processing.outerDom);
|
||||
setNamespaceCtx(processing, processing.realNode);
|
||||
|
||||
const newElements = processing.props;
|
||||
if (processing.isCreated) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
} from '../vnode/VNodeTags';
|
||||
import { throwIfTrue } from '../utils/throwIfTrue';
|
||||
import { captureFunctionComponent } from './FunctionComponent';
|
||||
import { captureClassComponent } from './ClassComponent';
|
||||
import { captureRender as captureClassComponent } from './ClassComponent';
|
||||
import { captureMemoComponent } from './MemoComponent';
|
||||
|
||||
export function bubbleRender() { }
|
||||
|
|
|
@ -12,7 +12,7 @@ export function bubbleRender(processing: VNode) {
|
|||
}
|
||||
|
||||
function updateTreeRoot(processing) {
|
||||
setNamespaceCtx(processing, processing.outerDom);
|
||||
setNamespaceCtx(processing, processing.realNode);
|
||||
|
||||
const updates = processing.updates;
|
||||
throwIfTrue(
|
||||
|
|
|
@ -118,15 +118,19 @@ export function callComponentWillUpdate(inst, newProps, newState, nextContext) {
|
|||
}
|
||||
|
||||
export function callComponentWillReceiveProps(inst, newProps: object, newContext: object) {
|
||||
const oldState = inst.state;
|
||||
if (inst.componentWillReceiveProps) {
|
||||
const oldState = inst.state;
|
||||
inst.componentWillReceiveProps(newProps, newContext);
|
||||
if (inst.state !== oldState) {
|
||||
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);
|
||||
if (inst.state !== oldState) {
|
||||
changeStateContent.call(inst, UpdateState.Override, inst.state, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -225,12 +225,9 @@ function submitAddition(vNode: VNode): void {
|
|||
let tag;
|
||||
while (parent !== null) {
|
||||
tag = parent.tag;
|
||||
if (tag === DomComponent) {
|
||||
if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) {
|
||||
parentDom = parent.realNode;
|
||||
break;
|
||||
} else if (tag === TreeRoot || tag === DomPortal) {
|
||||
parentDom = parent.outerDom;
|
||||
break;
|
||||
}
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
@ -292,12 +289,9 @@ function unmountDomComponents(vNode: VNode): void {
|
|||
let tag;
|
||||
while (parent !== null) {
|
||||
tag = parent.tag;
|
||||
if (tag === DomComponent) {
|
||||
if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) {
|
||||
currentParent = parent.realNode;
|
||||
break;
|
||||
} else if (tag === TreeRoot || tag === DomPortal) {
|
||||
currentParent = parent.outerDom;
|
||||
break;
|
||||
}
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
@ -312,7 +306,7 @@ function unmountDomComponents(vNode: VNode): void {
|
|||
removeChildDom(currentParent, node.realNode);
|
||||
} else if (node.tag === DomPortal) {
|
||||
if (node.child !== null) {
|
||||
currentParent = node.outerDom;
|
||||
currentParent = node.realNode;
|
||||
}
|
||||
} else {
|
||||
unmountVNode(node);
|
||||
|
@ -349,12 +343,9 @@ function submitClear(vNode: VNode): void {
|
|||
let tag;
|
||||
while (parent !== null) {
|
||||
tag = parent.tag;
|
||||
if (tag === DomComponent) {
|
||||
if (tag === DomComponent || tag === TreeRoot || tag === DomPortal) {
|
||||
parentDom = parent.realNode;
|
||||
break;
|
||||
} else if (tag === TreeRoot || tag === DomPortal) {
|
||||
parentDom = parent.outerDom;
|
||||
break;
|
||||
}
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ export class VNode {
|
|||
dirtyNodes: Array<VNode> | null = null; // 需要改动的节点数组
|
||||
shouldUpdate: boolean = false;
|
||||
childShouldUpdate: boolean = false;
|
||||
outerDom: any;
|
||||
task: any;
|
||||
|
||||
// 使用这个变量来记录修改前的值,用于恢复。
|
||||
|
@ -67,7 +66,7 @@ export class VNode {
|
|||
|
||||
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.key = key;
|
||||
|
||||
|
@ -75,10 +74,9 @@ export class VNode {
|
|||
|
||||
switch (tag) {
|
||||
case TreeRoot:
|
||||
this.outerDom = outerDom;
|
||||
this.realNode = realNode;
|
||||
this.task = null;
|
||||
this.toUpdateNodes = new Set<VNode>();
|
||||
this.realNode = null;
|
||||
this.updates = null;
|
||||
this.stateCallbacks = null;
|
||||
this.state = null;
|
||||
|
@ -138,6 +136,7 @@ export class VNode {
|
|||
this.stateCallbacks = null;
|
||||
this.isLazyComponent = true;
|
||||
this.lazyType = null;
|
||||
this.updates = null;
|
||||
break;
|
||||
case Fragment:
|
||||
break;
|
||||
|
|
|
@ -16,7 +16,6 @@ import {
|
|||
MemoComponent,
|
||||
SuspenseComponent,
|
||||
} from './VNodeTags';
|
||||
import { createUpdateArray } from '../UpdateHandler';
|
||||
import {
|
||||
TYPE_CONTEXT,
|
||||
TYPE_FORWARD_REF, TYPE_FRAGMENT,
|
||||
|
@ -39,8 +38,8 @@ const typeMap = {
|
|||
[TYPE_LAZY]: LazyComponent,
|
||||
};
|
||||
|
||||
const newVirtualNode = function(tag: VNodeTag, key?: null | string, vNodeProps?: any, outerDom?: any): VNode {
|
||||
return new VNode(tag, vNodeProps, key, outerDom);
|
||||
const newVirtualNode = function(tag: VNodeTag, key?: null | string, vNodeProps?: any, realNode?: any): VNode {
|
||||
return new VNode(tag, vNodeProps, key, realNode);
|
||||
};
|
||||
|
||||
function isClassComponent(comp: Function) {
|
||||
|
@ -100,7 +99,7 @@ export function createPortalVNode(portal) {
|
|||
const children = portal.children ?? [];
|
||||
const vNode = newVirtualNode(DomPortal, portal.key, children);
|
||||
vNode.shouldUpdate = true;
|
||||
vNode.outerDom = portal.outerDom;
|
||||
vNode.realNode = portal.realNode;
|
||||
return vNode;
|
||||
}
|
||||
|
||||
|
@ -137,7 +136,7 @@ export function createUndeterminedVNode(type, key, props) {
|
|||
export function createTreeRootVNode(container) {
|
||||
const vNode = newVirtualNode(TreeRoot, null, null, container);
|
||||
vNode.path += 0;
|
||||
createUpdateArray(vNode);
|
||||
vNode.updates = [];
|
||||
return vNode;
|
||||
}
|
||||
|
||||
|
@ -150,7 +149,7 @@ export function createVNode(tag: VNodeTag | string, ...secondArg) {
|
|||
vNode = newVirtualNode(TreeRoot, null, null, secondArg[0]);
|
||||
vNode.path += 0;
|
||||
|
||||
createUpdateArray(vNode);
|
||||
vNode.updates = [];
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,12 +24,10 @@ const LifecycleEffectArr = Update | Callback | Ref | Snapshot;
|
|||
|
||||
export class FlagUtils {
|
||||
static removeFlag(node: VNode, flag: number) {
|
||||
const flags = node.flags;
|
||||
node.flags = flags & (~flag);
|
||||
node.flags &= ~flag;
|
||||
}
|
||||
static removeLifecycleEffectFlags(node) {
|
||||
const flags = node.flags;
|
||||
node.flags = flags & (~LifecycleEffectArr);
|
||||
node.flags &= ~LifecycleEffectArr;
|
||||
}
|
||||
static hasAnyFlag(node: VNode) { // 有标志位
|
||||
return node.flags !== InitFlag;
|
||||
|
|
|
@ -210,7 +210,7 @@ function isPortalRoot(vNode, targetContainer) {
|
|||
while (topVNode !== null) {
|
||||
const grandTag = topVNode.tag;
|
||||
if (grandTag === TreeRoot || grandTag === DomPortal) {
|
||||
const topContainer = topVNode.outerDom;
|
||||
const topContainer = topVNode.realNode;
|
||||
// 如果topContainer是targetContainer,不需要在这里处理
|
||||
if (isSameContainer(topContainer, targetContainer)) {
|
||||
return true;
|
||||
|
@ -229,7 +229,7 @@ export function getExactNode(targetVNode, targetContainer) {
|
|||
let vNode = targetVNode;
|
||||
while (vNode !== null) {
|
||||
if (vNode.tag === TreeRoot || vNode.tag === DomPortal) {
|
||||
let container = vNode.outerDom;
|
||||
let container = vNode.realNode;
|
||||
if (isSameContainer(container, targetContainer)) {
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue