Match-id-d2b5a8a6155126b7ee1dfadc6df2e1f398f8d28b

This commit is contained in:
* 2022-03-17 20:34:41 +08:00 committed by *
parent 17ec96802e
commit 0fadb8bdf6
3 changed files with 53 additions and 25 deletions

View File

@ -2,7 +2,13 @@ import type { VNode } from '../Types';
import { FlagUtils } from '../vnode/VNodeFlags';
import { TYPE_COMMON_ELEMENT, TYPE_FRAGMENT, TYPE_PORTAL } from '../../external/JSXElementType';
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 {
isSameType,
getIteratorFn,
@ -112,7 +118,7 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
return null;
}
let resultNode = null;
let resultNode: VNode | null = null;
switch (newNodeType) {
case DiffCategory.TEXT_NODE: {
if (oldNode === null || oldNode.tag !== DomText) {
@ -172,9 +178,9 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
}
function transRightChildrenToArray(child) {
const rightChildrenArray = [];
const rightChildrenArray: VNode[] = [];
travelChildren(child, (node) => {
travelChildren(child, node => {
rightChildrenArray.push(node);
});
@ -183,11 +189,11 @@ function transRightChildrenToArray(child) {
function transLeftChildrenToMap(
startChild: VNode,
rightEndVNode: VNode | null
rightEndVNode: VNode | null,
): Map<string | number, VNode> {
const leftChildrenMap: Map<string | number, VNode> = new Map();
travelChildren(startChild, (node) => {
travelChildren(startChild, node => {
leftChildrenMap.set(node.key !== null ? node.key : node.eIndex, node);
}, node => node === rightEndVNode);
@ -214,25 +220,28 @@ function diffArrayNodesHandler(
parentNode: VNode,
firstChild: VNode | null,
newChildren: Array<any>,
isComparing: boolean
isComparing: boolean,
): VNode | null {
let resultingFirstChild: VNode | null = null;
let prevNewNode: VNode | null = null;
let oldNode = firstChild;
let nextOldNode = null;
let nextOldNode: VNode | null = null;
let theLastPosition = 0;
// 从左边开始的位置
let leftIdx = 0;
function appendNode(newNode) {
function appendNode(newNode: VNode) {
if (prevNewNode === null) {
resultingFirstChild = newNode;
newNode.cIndex = 0;
} else {
prevNewNode.next = newNode;
newNode.cIndex = prevNewNode.cIndex + 1;
}
newNode.path = newNode.parent.path + newNode.cIndex;
prevNewNode = newNode;
}
@ -269,15 +278,13 @@ function diffArrayNodesHandler(
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
newNode.eIndex = leftIdx;
newNode.cIndex = leftIdx;
newNode.path = newNode.parent.path + newNode.cIndex;
appendNode(newNode);
oldNode = nextOldNode;
}
let rightIdx = newChildren.length;
let rightEndOldNode; // 老节点中最右边匹配的节点引用 abcde --> abfde 则rightEndOldNode = c;
let rightNewNode = null; // 最右边匹配的节点引用 abcde --> abfde 则rightNewNode = d;
let rightNewNode: VNode | null = null; // 最右边匹配的节点引用 abcde --> abfde 则rightNewNode = d;
// 从后往前新资源的位置还没有到最末端旧的vNode也还没遍历完则可以考虑从后往前开始
if (rightIdx > leftIdx && oldNode !== null) {
const rightRemainingOldChildren = transRightChildrenToArray(oldNode);
@ -347,7 +354,9 @@ function diffArrayNodesHandler(
let isDirectAdd = false;
// TODO: 是否可以扩大至非dom类型节点
// 如果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;
}
for (; leftIdx < rightIdx; leftIdx++) {
@ -367,7 +376,7 @@ function diffArrayNodesHandler(
if (rightNewNode) {
appendNode(rightNewNode);
setVNodesCIndex(rightNewNode, prevNewNode.cIndex + 1);
setVNodesCIndex(rightNewNode.next, prevNewNode.cIndex + 1);
}
return resultingFirstChild;
@ -380,7 +389,7 @@ function diffArrayNodesHandler(
const eIndexes: Array<number> = []; // 记录 eIndex 值
const result: Array<number> = []; // 记录最长子序列在eIndexes中的 index 值
const preIndex: Array<number> = []; // 贪心算法在替换的过程中会使得数组不正确通过记录preIndex找到正确值
const reuseNodes = []; // 记录复用的 VNode
const reuseNodes: (VNode | null)[] = []; // 记录复用的 VNode
let i = 0;
let oldNodeFromMap;
let last;
@ -394,7 +403,7 @@ function diffArrayNodesHandler(
}
if (oldNodeFromMap !== null) {
let eIndex = newNode.eIndex;
const eIndex = newNode.eIndex;
eIndexes.push(eIndex);
last = eIndexes[result[result.length - 1]];
if (eIndex > last || last === undefined) { // 大的 eIndex直接放在最后
@ -455,7 +464,7 @@ function diffArrayNodesHandler(
if (rightNewNode) {
appendNode(rightNewNode);
setVNodesCIndex(rightNewNode, prevNewNode.cIndex + 1);
setVNodesCIndex(rightNewNode.next, prevNewNode.cIndex + 1);
}
return resultingFirstChild;
@ -463,7 +472,7 @@ function diffArrayNodesHandler(
// 设置vNode中的cIndex属性cIndex是节点在children中的位置
function setVNodesCIndex(startChild: VNode, startIdx: number) {
let node = startChild;
let node: VNode | null = startChild;
let idx = startIdx;
while (node !== null) {
@ -479,7 +488,7 @@ function diffIteratorNodesHandler(
parentNode: VNode,
firstChild: VNode | null,
newChildrenIterable: Iterable<any>,
isComparing: boolean
isComparing: boolean,
): VNode | null {
const iteratorFn = getIteratorFn(newChildrenIterable);
const iteratorObj = iteratorFn.call(newChildrenIterable);
@ -500,7 +509,7 @@ function diffStringNodeHandler(
parentNode: VNode,
newChild: any,
firstChildVNode: VNode,
isComparing: boolean
isComparing: boolean,
) {
let newTextNode: VNode | null = null;
@ -530,7 +539,7 @@ function diffObjectNodeHandler(
firstChild: VNode | null,
newChild: any,
firstChildVNode: VNode,
isComparing: boolean
isComparing: boolean,
) {
let canReuseNode: VNode | null = null;
@ -612,7 +621,7 @@ export function createChildrenByDiff(
parentNode: VNode,
firstChild: VNode | null,
newChild: any,
isComparing: boolean
isComparing: boolean,
): VNode | null {
const isFragment = isNoKeyFragment(newChild);
newChild = isFragment ? newChild.props.children : newChild;

View File

@ -25,7 +25,7 @@ import {
TYPE_SUSPENSE,
} from '../../external/JSXElementType';
import { VNode } from './VNode';
import {JSXElement} from '../Types';
import { JSXElement } from '../Types';
const typeLazyMap = {
[TYPE_FORWARD_REF]: ForwardRef,
@ -187,6 +187,26 @@ export function onlyUpdateChildVNodes(processing: VNode): VNode | null {
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;
}

View File

@ -51,7 +51,6 @@
"prefer-object-spread": true,
"typeof-compare": true,
"cyclomatic-complexity": [true, 20],
"max-file-line-count": [true, 500],
"prefer-readonly": true,
"prefer-const": true,
"radix": true,