Match-id-d2b5a8a6155126b7ee1dfadc6df2e1f398f8d28b
This commit is contained in:
parent
17ec96802e
commit
0fadb8bdf6
|
@ -2,7 +2,13 @@ import type { VNode } from '../Types';
|
||||||
import { FlagUtils } from '../vnode/VNodeFlags';
|
import { FlagUtils } from '../vnode/VNodeFlags';
|
||||||
import { TYPE_COMMON_ELEMENT, TYPE_FRAGMENT, TYPE_PORTAL } from '../../external/JSXElementType';
|
import { TYPE_COMMON_ELEMENT, TYPE_FRAGMENT, TYPE_PORTAL } from '../../external/JSXElementType';
|
||||||
import { DomText, DomPortal, Fragment, DomComponent } from '../vnode/VNodeTags';
|
import { DomText, DomPortal, Fragment, DomComponent } from '../vnode/VNodeTags';
|
||||||
import {updateVNode, createVNodeFromElement, createFragmentVNode, createPortalVNode, createDomTextVNode} from '../vnode/VNodeCreator';
|
import {
|
||||||
|
updateVNode,
|
||||||
|
createVNodeFromElement,
|
||||||
|
createFragmentVNode,
|
||||||
|
createPortalVNode,
|
||||||
|
createDomTextVNode,
|
||||||
|
} from '../vnode/VNodeCreator';
|
||||||
import {
|
import {
|
||||||
isSameType,
|
isSameType,
|
||||||
getIteratorFn,
|
getIteratorFn,
|
||||||
|
@ -112,7 +118,7 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let resultNode = null;
|
let resultNode: VNode | null = null;
|
||||||
switch (newNodeType) {
|
switch (newNodeType) {
|
||||||
case DiffCategory.TEXT_NODE: {
|
case DiffCategory.TEXT_NODE: {
|
||||||
if (oldNode === null || oldNode.tag !== DomText) {
|
if (oldNode === null || oldNode.tag !== DomText) {
|
||||||
|
@ -172,9 +178,9 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function transRightChildrenToArray(child) {
|
function transRightChildrenToArray(child) {
|
||||||
const rightChildrenArray = [];
|
const rightChildrenArray: VNode[] = [];
|
||||||
|
|
||||||
travelChildren(child, (node) => {
|
travelChildren(child, node => {
|
||||||
rightChildrenArray.push(node);
|
rightChildrenArray.push(node);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -183,11 +189,11 @@ function transRightChildrenToArray(child) {
|
||||||
|
|
||||||
function transLeftChildrenToMap(
|
function transLeftChildrenToMap(
|
||||||
startChild: VNode,
|
startChild: VNode,
|
||||||
rightEndVNode: VNode | null
|
rightEndVNode: VNode | null,
|
||||||
): Map<string | number, VNode> {
|
): Map<string | number, VNode> {
|
||||||
const leftChildrenMap: Map<string | number, VNode> = new Map();
|
const leftChildrenMap: Map<string | number, VNode> = new Map();
|
||||||
|
|
||||||
travelChildren(startChild, (node) => {
|
travelChildren(startChild, node => {
|
||||||
leftChildrenMap.set(node.key !== null ? node.key : node.eIndex, node);
|
leftChildrenMap.set(node.key !== null ? node.key : node.eIndex, node);
|
||||||
}, node => node === rightEndVNode);
|
}, node => node === rightEndVNode);
|
||||||
|
|
||||||
|
@ -214,25 +220,28 @@ function diffArrayNodesHandler(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
firstChild: VNode | null,
|
firstChild: VNode | null,
|
||||||
newChildren: Array<any>,
|
newChildren: Array<any>,
|
||||||
isComparing: boolean
|
isComparing: boolean,
|
||||||
): VNode | null {
|
): VNode | null {
|
||||||
let resultingFirstChild: VNode | null = null;
|
let resultingFirstChild: VNode | null = null;
|
||||||
|
|
||||||
let prevNewNode: VNode | null = null;
|
let prevNewNode: VNode | null = null;
|
||||||
|
|
||||||
let oldNode = firstChild;
|
let oldNode = firstChild;
|
||||||
let nextOldNode = null;
|
let nextOldNode: VNode | null = null;
|
||||||
|
|
||||||
let theLastPosition = 0;
|
let theLastPosition = 0;
|
||||||
// 从左边开始的位置
|
// 从左边开始的位置
|
||||||
let leftIdx = 0;
|
let leftIdx = 0;
|
||||||
|
|
||||||
function appendNode(newNode) {
|
function appendNode(newNode: VNode) {
|
||||||
if (prevNewNode === null) {
|
if (prevNewNode === null) {
|
||||||
resultingFirstChild = newNode;
|
resultingFirstChild = newNode;
|
||||||
|
newNode.cIndex = 0;
|
||||||
} else {
|
} else {
|
||||||
prevNewNode.next = newNode;
|
prevNewNode.next = newNode;
|
||||||
|
newNode.cIndex = prevNewNode.cIndex + 1;
|
||||||
}
|
}
|
||||||
|
newNode.path = newNode.parent.path + newNode.cIndex;
|
||||||
prevNewNode = newNode;
|
prevNewNode = newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,15 +278,13 @@ function diffArrayNodesHandler(
|
||||||
|
|
||||||
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
|
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
|
||||||
newNode.eIndex = leftIdx;
|
newNode.eIndex = leftIdx;
|
||||||
newNode.cIndex = leftIdx;
|
|
||||||
newNode.path = newNode.parent.path + newNode.cIndex;
|
|
||||||
appendNode(newNode);
|
appendNode(newNode);
|
||||||
oldNode = nextOldNode;
|
oldNode = nextOldNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rightIdx = newChildren.length;
|
let rightIdx = newChildren.length;
|
||||||
let rightEndOldNode; // 老节点中最右边匹配的节点引用 abcde --> abfde 则rightEndOldNode = c;
|
let rightEndOldNode; // 老节点中最右边匹配的节点引用 abcde --> abfde 则rightEndOldNode = c;
|
||||||
let rightNewNode = null; // 最右边匹配的节点引用 abcde --> abfde 则rightNewNode = d;
|
let rightNewNode: VNode | null = null; // 最右边匹配的节点引用 abcde --> abfde 则rightNewNode = d;
|
||||||
// 从后往前,新资源的位置还没有到最末端,旧的vNode也还没遍历完,则可以考虑从后往前开始
|
// 从后往前,新资源的位置还没有到最末端,旧的vNode也还没遍历完,则可以考虑从后往前开始
|
||||||
if (rightIdx > leftIdx && oldNode !== null) {
|
if (rightIdx > leftIdx && oldNode !== null) {
|
||||||
const rightRemainingOldChildren = transRightChildrenToArray(oldNode);
|
const rightRemainingOldChildren = transRightChildrenToArray(oldNode);
|
||||||
|
@ -343,11 +350,13 @@ function diffArrayNodesHandler(
|
||||||
|
|
||||||
// 4. 新节点还有一部分,但是老节点已经没有了
|
// 4. 新节点还有一部分,但是老节点已经没有了
|
||||||
if (oldNode === null) {
|
if (oldNode === null) {
|
||||||
|
|
||||||
let isDirectAdd = false;
|
let isDirectAdd = false;
|
||||||
// TODO: 是否可以扩大至非dom类型节点
|
// TODO: 是否可以扩大至非dom类型节点
|
||||||
// 如果dom节点在上次添加前没有节点,说明本次添加时,可以直接添加到最后,不需要通过 getSiblingDom 函数找到 before 节点
|
// 如果dom节点在上次添加前没有节点,说明本次添加时,可以直接添加到最后,不需要通过 getSiblingDom 函数找到 before 节点
|
||||||
if (parentNode.tag === DomComponent && parentNode.oldProps?.children?.length === 0 && rightIdx - leftIdx === newChildren.length) {
|
if (parentNode.tag === DomComponent &&
|
||||||
|
parentNode.oldProps?.children?.length === 0 &&
|
||||||
|
rightIdx - leftIdx === newChildren.length) {
|
||||||
isDirectAdd = true;
|
isDirectAdd = true;
|
||||||
}
|
}
|
||||||
for (; leftIdx < rightIdx; leftIdx++) {
|
for (; leftIdx < rightIdx; leftIdx++) {
|
||||||
|
@ -367,7 +376,7 @@ function diffArrayNodesHandler(
|
||||||
|
|
||||||
if (rightNewNode) {
|
if (rightNewNode) {
|
||||||
appendNode(rightNewNode);
|
appendNode(rightNewNode);
|
||||||
setVNodesCIndex(rightNewNode, prevNewNode.cIndex + 1);
|
setVNodesCIndex(rightNewNode.next, prevNewNode.cIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultingFirstChild;
|
return resultingFirstChild;
|
||||||
|
@ -380,7 +389,7 @@ function diffArrayNodesHandler(
|
||||||
const eIndexes: Array<number> = []; // 记录 eIndex 值
|
const eIndexes: Array<number> = []; // 记录 eIndex 值
|
||||||
const result: Array<number> = []; // 记录最长子序列在eIndexes中的 index 值
|
const result: Array<number> = []; // 记录最长子序列在eIndexes中的 index 值
|
||||||
const preIndex: Array<number> = []; // 贪心算法在替换的过程中会使得数组不正确,通过记录preIndex找到正确值
|
const preIndex: Array<number> = []; // 贪心算法在替换的过程中会使得数组不正确,通过记录preIndex找到正确值
|
||||||
const reuseNodes = []; // 记录复用的 VNode
|
const reuseNodes: (VNode | null)[] = []; // 记录复用的 VNode
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let oldNodeFromMap;
|
let oldNodeFromMap;
|
||||||
let last;
|
let last;
|
||||||
|
@ -394,7 +403,7 @@ function diffArrayNodesHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldNodeFromMap !== null) {
|
if (oldNodeFromMap !== null) {
|
||||||
let eIndex = newNode.eIndex;
|
const eIndex = newNode.eIndex;
|
||||||
eIndexes.push(eIndex);
|
eIndexes.push(eIndex);
|
||||||
last = eIndexes[result[result.length - 1]];
|
last = eIndexes[result[result.length - 1]];
|
||||||
if (eIndex > last || last === undefined) { // 大的 eIndex直接放在最后
|
if (eIndex > last || last === undefined) { // 大的 eIndex直接放在最后
|
||||||
|
@ -455,7 +464,7 @@ function diffArrayNodesHandler(
|
||||||
|
|
||||||
if (rightNewNode) {
|
if (rightNewNode) {
|
||||||
appendNode(rightNewNode);
|
appendNode(rightNewNode);
|
||||||
setVNodesCIndex(rightNewNode, prevNewNode.cIndex + 1);
|
setVNodesCIndex(rightNewNode.next, prevNewNode.cIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultingFirstChild;
|
return resultingFirstChild;
|
||||||
|
@ -463,7 +472,7 @@ function diffArrayNodesHandler(
|
||||||
|
|
||||||
// 设置vNode中的cIndex属性,cIndex是节点在children中的位置
|
// 设置vNode中的cIndex属性,cIndex是节点在children中的位置
|
||||||
function setVNodesCIndex(startChild: VNode, startIdx: number) {
|
function setVNodesCIndex(startChild: VNode, startIdx: number) {
|
||||||
let node = startChild;
|
let node: VNode | null = startChild;
|
||||||
let idx = startIdx;
|
let idx = startIdx;
|
||||||
|
|
||||||
while (node !== null) {
|
while (node !== null) {
|
||||||
|
@ -479,7 +488,7 @@ function diffIteratorNodesHandler(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
firstChild: VNode | null,
|
firstChild: VNode | null,
|
||||||
newChildrenIterable: Iterable<any>,
|
newChildrenIterable: Iterable<any>,
|
||||||
isComparing: boolean
|
isComparing: boolean,
|
||||||
): VNode | null {
|
): VNode | null {
|
||||||
const iteratorFn = getIteratorFn(newChildrenIterable);
|
const iteratorFn = getIteratorFn(newChildrenIterable);
|
||||||
const iteratorObj = iteratorFn.call(newChildrenIterable);
|
const iteratorObj = iteratorFn.call(newChildrenIterable);
|
||||||
|
@ -500,7 +509,7 @@ function diffStringNodeHandler(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
newChild: any,
|
newChild: any,
|
||||||
firstChildVNode: VNode,
|
firstChildVNode: VNode,
|
||||||
isComparing: boolean
|
isComparing: boolean,
|
||||||
) {
|
) {
|
||||||
let newTextNode: VNode | null = null;
|
let newTextNode: VNode | null = null;
|
||||||
|
|
||||||
|
@ -530,7 +539,7 @@ function diffObjectNodeHandler(
|
||||||
firstChild: VNode | null,
|
firstChild: VNode | null,
|
||||||
newChild: any,
|
newChild: any,
|
||||||
firstChildVNode: VNode,
|
firstChildVNode: VNode,
|
||||||
isComparing: boolean
|
isComparing: boolean,
|
||||||
) {
|
) {
|
||||||
let canReuseNode: VNode | null = null;
|
let canReuseNode: VNode | null = null;
|
||||||
|
|
||||||
|
@ -612,7 +621,7 @@ export function createChildrenByDiff(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
firstChild: VNode | null,
|
firstChild: VNode | null,
|
||||||
newChild: any,
|
newChild: any,
|
||||||
isComparing: boolean
|
isComparing: boolean,
|
||||||
): VNode | null {
|
): VNode | null {
|
||||||
const isFragment = isNoKeyFragment(newChild);
|
const isFragment = isNoKeyFragment(newChild);
|
||||||
newChild = isFragment ? newChild.props.children : newChild;
|
newChild = isFragment ? newChild.props.children : newChild;
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {
|
||||||
TYPE_SUSPENSE,
|
TYPE_SUSPENSE,
|
||||||
} from '../../external/JSXElementType';
|
} from '../../external/JSXElementType';
|
||||||
import { VNode } from './VNode';
|
import { VNode } from './VNode';
|
||||||
import {JSXElement} from '../Types';
|
import { JSXElement } from '../Types';
|
||||||
|
|
||||||
const typeLazyMap = {
|
const typeLazyMap = {
|
||||||
[TYPE_FORWARD_REF]: ForwardRef,
|
[TYPE_FORWARD_REF]: ForwardRef,
|
||||||
|
@ -187,6 +187,26 @@ export function onlyUpdateChildVNodes(processing: VNode): VNode | null {
|
||||||
return processing.child;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 当跳过子树更新时,需要更新子树path
|
||||||
|
if (processing.child && processing.path !== processing.child.path.slice(0, processing.path.length)) {
|
||||||
|
// 更新子树path
|
||||||
|
const queue: VNode[] = [processing];
|
||||||
|
while (queue.length) {
|
||||||
|
const vNode = queue.shift()!;
|
||||||
|
|
||||||
|
// 忽略processing path重新计算
|
||||||
|
vNode.path = vNode.parent.path + vNode.cIndex;
|
||||||
|
const child = vNode.child;
|
||||||
|
if (child) {
|
||||||
|
queue.push(child);
|
||||||
|
let sibling = child.next;
|
||||||
|
while (sibling) {
|
||||||
|
queue.push(sibling);
|
||||||
|
sibling = sibling.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// 子树无需工作
|
// 子树无需工作
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,6 @@
|
||||||
"prefer-object-spread": true,
|
"prefer-object-spread": true,
|
||||||
"typeof-compare": true,
|
"typeof-compare": true,
|
||||||
"cyclomatic-complexity": [true, 20],
|
"cyclomatic-complexity": [true, 20],
|
||||||
"max-file-line-count": [true, 500],
|
|
||||||
"prefer-readonly": true,
|
"prefer-readonly": true,
|
||||||
"prefer-const": true,
|
"prefer-const": true,
|
||||||
"radix": true,
|
"radix": true,
|
||||||
|
|
Loading…
Reference in New Issue