Match-id-afab855d892ab9467bc56b12800c572141a4c2f0
This commit is contained in:
parent
7c0fbfd85a
commit
cac25b039b
|
@ -164,6 +164,7 @@ export function submitDomUpdate(tag: string, vNode: VNode) {
|
||||||
const type = vNode.type;
|
const type = vNode.type;
|
||||||
const changeList = vNode.changeList;
|
const changeList = vNode.changeList;
|
||||||
vNode.changeList = null;
|
vNode.changeList = null;
|
||||||
|
|
||||||
if (changeList !== null) {
|
if (changeList !== null) {
|
||||||
saveVNode(vNode, element);
|
saveVNode(vNode, element);
|
||||||
updateVNodeProps(element, newProps);
|
updateVNodeProps(element, newProps);
|
||||||
|
|
|
@ -38,11 +38,10 @@ export function startUpdate(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFirstCustomDom(treeRoot: VNode): Element | Text | null {
|
export function getFirstCustomDom(treeRoot: VNode): Element | Text | null {
|
||||||
const firstChild = getFirstChild(treeRoot);
|
if (!treeRoot.child) {
|
||||||
if (!firstChild) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstChild.realNode;
|
return treeRoot.child.realNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,12 +132,20 @@ export function calcStartUpdateVNode(treeRoot: VNode) {
|
||||||
let node = treeRoot;
|
let node = treeRoot;
|
||||||
for (let i = 1; i < startNodePath.length; i++) {
|
for (let i = 1; i < startNodePath.length; i++) {
|
||||||
let pathIndex = startNodePath[i];
|
let pathIndex = startNodePath[i];
|
||||||
node = node.children[pathIndex];
|
node = getChildByIndex(node, pathIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getChildByIndex(vNode: VNode, idx: number) {
|
||||||
|
let node = vNode.child;
|
||||||
|
for (let i = 0; i < idx; i++) {
|
||||||
|
node = node.next;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
// 判断数组中节点的path的idx元素是否都相等
|
// 判断数组中节点的path的idx元素是否都相等
|
||||||
function isEqualByIndex(idx: number, nodes: Array<VNode>) {
|
function isEqualByIndex(idx: number, nodes: Array<VNode>) {
|
||||||
let val = nodes[0].path[idx];
|
let val = nodes[0].path[idx];
|
||||||
|
@ -225,12 +233,11 @@ function buildVNodeTree(treeRoot: VNode) {
|
||||||
// 捕获创建 vNodes
|
// 捕获创建 vNodes
|
||||||
const next = captureVNode(processing);
|
const next = captureVNode(processing);
|
||||||
|
|
||||||
// @ts-ignore
|
if (next === null) {
|
||||||
if (!next || !next.length) {
|
|
||||||
// 如果没有产生新的,那么就完成当前节点,向上遍历
|
// 如果没有产生新的,那么就完成当前节点,向上遍历
|
||||||
bubbleVNode(processing);
|
bubbleVNode(processing);
|
||||||
} else {
|
} else {
|
||||||
processing = next[0];
|
processing = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessingVNode.val = null;
|
ProcessingVNode.val = null;
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
isIteratorType,
|
isIteratorType,
|
||||||
isObjectType,
|
isObjectType,
|
||||||
} from './DiffTools';
|
} from './DiffTools';
|
||||||
import {getSiblingVNode} from '../vnode/VNodeUtils';
|
import {getSiblingVNode, travelChildren} from '../vnode/VNodeUtils';
|
||||||
|
|
||||||
enum DiffCategory {
|
enum DiffCategory {
|
||||||
TEXT_NODE = 'TEXT_NODE',
|
TEXT_NODE = 'TEXT_NODE',
|
||||||
|
@ -32,15 +32,17 @@ function deleteVNode(parentNode: VNode, delVNode: VNode): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清除多个节点
|
// 清除多个节点
|
||||||
function deleteVNodes(parentVNode: VNode, currentChildren: Array<VNode>, startIdx: number, endVNode?: VNode): void {
|
function deleteVNodes(parentVNode: VNode, startDelVNode: VNode, endVNode?: VNode): void {
|
||||||
if (currentChildren) {
|
let node = startDelVNode;
|
||||||
for (let i = startIdx; i < currentChildren.length; i++) {
|
|
||||||
const delVNode = currentChildren[i];
|
while (node !== null) {
|
||||||
if (delVNode === endVNode) {
|
if (node === endVNode) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
deleteVNode(parentVNode, delVNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteVNode(parentVNode, node);
|
||||||
|
|
||||||
|
node = node.next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ function checkCanReuseNode(oldNode: VNode | null, newChild: any): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeType(parentNode: VNode, newChild: any): string {
|
function getNodeType(newChild: any): string {
|
||||||
if (newChild === null) {
|
if (newChild === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +105,7 @@ function setVNodeAdditionFlag(newNode: VNode, lastPosition: number, isComparing:
|
||||||
|
|
||||||
// 获取新节点
|
// 获取新节点
|
||||||
function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
||||||
const newNodeType = getNodeType(parentNode, newChild);
|
const newNodeType = getNodeType(newChild);
|
||||||
if (newNodeType === null) {
|
if (newNodeType === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -159,29 +161,38 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
|
||||||
|
|
||||||
if (resultNode) {
|
if (resultNode) {
|
||||||
resultNode.parent = parentNode;
|
resultNode.parent = parentNode;
|
||||||
|
resultNode.next = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultNode;
|
return resultNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function transRightChildrenToArray(child) {
|
||||||
|
const rightChildrenArray = [];
|
||||||
|
|
||||||
|
travelChildren(child, (node) => {
|
||||||
|
rightChildrenArray.push(node);
|
||||||
|
});
|
||||||
|
|
||||||
|
return rightChildrenArray;
|
||||||
|
}
|
||||||
|
|
||||||
function transLeftChildrenToMap(
|
function transLeftChildrenToMap(
|
||||||
parentVNode: VNode,
|
startChild: VNode,
|
||||||
currentChildren: Array<VNode>,
|
|
||||||
startIdx: number,
|
|
||||||
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();
|
||||||
for (let i = startIdx; i < currentChildren.length; i++) {
|
|
||||||
const currentChild = currentChildren[i];
|
travelChildren(startChild, (node) => {
|
||||||
if (currentChild === rightEndVNode) {
|
leftChildrenMap.set(node.key !== null ? node.key : node.eIndex, node);
|
||||||
return leftChildrenMap;
|
}, (node) => {
|
||||||
}
|
return node === rightEndVNode;
|
||||||
leftChildrenMap.set(currentChild.key !== null ? currentChild.key : currentChild.eIndex, currentChild);
|
});
|
||||||
}
|
|
||||||
return leftChildrenMap;
|
return leftChildrenMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOldNodeFromMap(parentNode: VNode, nodeMap: Map<string | number, VNode>, newIdx: number, newChild: any) {
|
function getOldNodeFromMap(nodeMap: Map<string | number, VNode>, newIdx: number, newChild: any) {
|
||||||
if (isTextType(newChild)) {
|
if (isTextType(newChild)) {
|
||||||
return nodeMap.get(newIdx) || null;
|
return nodeMap.get(newIdx) || null;
|
||||||
}
|
}
|
||||||
|
@ -199,16 +210,29 @@ function getOldNodeFromMap(parentNode: VNode, nodeMap: Map<string | number, VNod
|
||||||
// diff数组类型的节点,核心算法
|
// diff数组类型的节点,核心算法
|
||||||
function diffArrayNodes(
|
function diffArrayNodes(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
currentChildren: Array<VNode> | null,
|
firstChild: VNode | null,
|
||||||
newChildren: Array<any>,
|
newChildren: Array<any>,
|
||||||
isComparing: boolean = true
|
isComparing: boolean = true
|
||||||
): Array<VNode> | null {
|
): VNode | null {
|
||||||
const resultChildren: Array<VNode> = [];
|
let resultingFirstChild: VNode | null = null;
|
||||||
let oldNode = (currentChildren.length > 0) ? currentChildren[0] : null;
|
|
||||||
|
let prevNewNode: VNode | null = null;
|
||||||
|
|
||||||
|
let oldNode = firstChild;
|
||||||
|
let nextOldNode = null;
|
||||||
|
|
||||||
let theLastPosition = 0;
|
let theLastPosition = 0;
|
||||||
// 从左边开始的位置
|
// 从左边开始的位置
|
||||||
let leftIdx = 0;
|
let leftIdx = 0;
|
||||||
let nextOldNode = null;
|
|
||||||
|
function appendNode(newNode) {
|
||||||
|
if (prevNewNode === null) {
|
||||||
|
resultingFirstChild = newNode;
|
||||||
|
} else {
|
||||||
|
prevNewNode.next = newNode;
|
||||||
|
}
|
||||||
|
prevNewNode = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. 从左侧开始比对currentVNode和newChildren,若不能复用则跳出循环
|
// 1. 从左侧开始比对currentVNode和newChildren,若不能复用则跳出循环
|
||||||
for (; oldNode !== null && leftIdx < newChildren.length; leftIdx++) {
|
for (; oldNode !== null && leftIdx < newChildren.length; leftIdx++) {
|
||||||
|
@ -241,16 +265,17 @@ function diffArrayNodes(
|
||||||
|
|
||||||
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
|
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
|
||||||
newNode.eIndex = leftIdx;
|
newNode.eIndex = leftIdx;
|
||||||
resultChildren.push(newNode);
|
setCIndex(newNode, leftIdx);
|
||||||
|
appendNode(newNode);
|
||||||
oldNode = nextOldNode;
|
oldNode = nextOldNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rightIdx = newChildren.length;
|
let rightIdx = newChildren.length;
|
||||||
let rightEndOldNode; // 老节点中最右边不匹配的节点引用 abcde --> abfde 则rightEndOldNode = f;
|
let rightEndOldNode; // 老节点中最右边匹配的节点引用 abcde --> abfde 则rightEndOldNode = c;
|
||||||
const rightNewNodes: Array<VNode> = []; // 最右边匹配的节点引用 abcde --> abfde rightNewNode = [d, e];
|
let rightNewNode = null; // 最右边匹配的节点引用 abcde --> abfde 则rightNewNode = d;
|
||||||
// 从后往前,新资源的位置还没有到最末端,旧的vNode也还没遍历完,则可以考虑从后往前开始
|
// 从后往前,新资源的位置还没有到最末端,旧的vNode也还没遍历完,则可以考虑从后往前开始
|
||||||
if (rightIdx > leftIdx && oldNode !== null) {
|
if (rightIdx > leftIdx && oldNode !== null) {
|
||||||
const rightRemainingOldChildren = currentChildren.slice(leftIdx);
|
const rightRemainingOldChildren = transRightChildrenToArray(oldNode);
|
||||||
let rightOldIndex = rightRemainingOldChildren.length - 1;
|
let rightOldIndex = rightRemainingOldChildren.length - 1;
|
||||||
|
|
||||||
// 2. 从右侧开始比对currentVNode和newChildren,若不能复用则跳出循环
|
// 2. 从右侧开始比对currentVNode和newChildren,若不能复用则跳出循环
|
||||||
|
@ -272,7 +297,13 @@ function diffArrayNodes(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rightNewNodes.unshift(newNode);
|
// 链接起来
|
||||||
|
if (rightNewNode === null) {
|
||||||
|
rightNewNode = newNode;
|
||||||
|
} else {
|
||||||
|
newNode.next = rightNewNode;
|
||||||
|
rightNewNode = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
if (isComparing && rightOldNode && newNode.isCreated) {
|
if (isComparing && rightOldNode && newNode.isCreated) {
|
||||||
deleteVNode(parentNode, rightOldNode);
|
deleteVNode(parentNode, rightOldNode);
|
||||||
|
@ -288,10 +319,15 @@ function diffArrayNodes(
|
||||||
// 3. 新节点已经处理完成
|
// 3. 新节点已经处理完成
|
||||||
if (leftIdx === rightIdx) {
|
if (leftIdx === rightIdx) {
|
||||||
if (isComparing) {
|
if (isComparing) {
|
||||||
deleteVNodes(parentNode, currentChildren, leftIdx, rightEndOldNode);
|
deleteVNodes(parentNode, oldNode, rightEndOldNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mergeResultChildren(resultChildren, rightNewNodes);
|
if (rightNewNode) {
|
||||||
|
appendNode(rightNewNode);
|
||||||
|
setVNodesCIndex(rightNewNode, prevNewNode.cIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultingFirstChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 新节点还有一部分,但是老节点已经没有了
|
// 4. 新节点还有一部分,但是老节点已经没有了
|
||||||
|
@ -302,18 +338,23 @@ function diffArrayNodes(
|
||||||
if (newNode !== null) {
|
if (newNode !== null) {
|
||||||
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
|
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
|
||||||
newNode.eIndex = leftIdx;
|
newNode.eIndex = leftIdx;
|
||||||
resultChildren.push(newNode);
|
appendNode(newNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mergeResultChildren(resultChildren, rightNewNodes);
|
if (rightNewNode) {
|
||||||
|
appendNode(rightNewNode);
|
||||||
|
setVNodesCIndex(rightNewNode, prevNewNode.cIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultingFirstChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 新节点还有一部分,但是老节点也还有一部分
|
// 5. 新节点还有一部分,但是老节点也还有一部分
|
||||||
// 把剩下的currentVNode转成Map
|
// 把剩下的currentVNode转成Map
|
||||||
const leftChildrenMap = transLeftChildrenToMap(parentNode, currentChildren, currentChildren.indexOf(oldNode), rightEndOldNode);
|
const leftChildrenMap = transLeftChildrenToMap(oldNode, rightEndOldNode);
|
||||||
for (; leftIdx < rightIdx; leftIdx++) {
|
for (; leftIdx < rightIdx; leftIdx++) {
|
||||||
const oldNodeFromMap = getOldNodeFromMap(parentNode, leftChildrenMap, leftIdx, newChildren[leftIdx]);
|
const oldNodeFromMap = getOldNodeFromMap(leftChildrenMap, leftIdx, newChildren[leftIdx]);
|
||||||
const newNode = getNewNode(parentNode, newChildren[leftIdx], oldNodeFromMap);
|
const newNode = getNewNode(parentNode, newChildren[leftIdx], oldNodeFromMap);
|
||||||
if (newNode !== null) {
|
if (newNode !== null) {
|
||||||
if (isComparing && !newNode.isCreated) {
|
if (isComparing && !newNode.isCreated) {
|
||||||
|
@ -323,53 +364,59 @@ function diffArrayNodes(
|
||||||
|
|
||||||
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
|
theLastPosition = setVNodeAdditionFlag(newNode, theLastPosition, isComparing);
|
||||||
newNode.eIndex = leftIdx;
|
newNode.eIndex = leftIdx;
|
||||||
resultChildren.push(newNode);
|
appendNode(newNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isComparing) {
|
if (isComparing) {
|
||||||
leftChildrenMap.forEach(child => deleteVNode(parentNode, child));
|
leftChildrenMap.forEach(child => {
|
||||||
|
deleteVNode(parentNode, child);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return mergeResultChildren(resultChildren, rightNewNodes);
|
if (rightNewNode) {
|
||||||
|
appendNode(rightNewNode);
|
||||||
|
setVNodesCIndex(rightNewNode, prevNewNode.cIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultingFirstChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置vNode中的cIndex属性,cIndex是节点在children中的位置
|
// 设置vNode中的cIndex属性,cIndex是节点在children中的位置
|
||||||
function setVNodeCIndex(resultChildren) {
|
function setVNodesCIndex(startChild: VNode, startIdx: number) {
|
||||||
resultChildren.forEach((node, idx) => {
|
let node = startChild;
|
||||||
|
let idx = startIdx;
|
||||||
|
|
||||||
|
while (node !== null) {
|
||||||
node.cIndex = idx;
|
node.cIndex = idx;
|
||||||
updateVNodePath(node);
|
updateVNodePath(node);
|
||||||
});
|
node = node.next;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeResultChildren(resultChildren: Array<VNode>, rightNewNodes: Array<VNode>): Array<VNode> {
|
function setCIndex(vNode: VNode, idx: number) {
|
||||||
if (rightNewNodes) {
|
vNode.cIndex = idx;
|
||||||
resultChildren.push(...rightNewNodes);
|
updateVNodePath(vNode);
|
||||||
}
|
|
||||||
|
|
||||||
// 设置vNode中的cIndex属性,cIndex是节点在children中的位置
|
|
||||||
setVNodeCIndex(resultChildren);
|
|
||||||
|
|
||||||
return resultChildren;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新节点是数组类型
|
// 新节点是数组类型
|
||||||
function diffArrayNodesHandler(
|
function diffArrayNodesHandler(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
currentVNode: Array<VNode> | null,
|
firstChild: VNode | null,
|
||||||
newChildren: Array<any>,
|
newChildren: Array<any>,
|
||||||
isComparing: boolean = true
|
isComparing: boolean = true
|
||||||
): Array<VNode> | null {
|
): VNode | null {
|
||||||
return diffArrayNodes(parentNode, currentVNode, newChildren, isComparing);
|
return diffArrayNodes(parentNode, firstChild, newChildren, isComparing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新节点是迭代器类型
|
// 新节点是迭代器类型
|
||||||
function diffIteratorNodesHandler(
|
function diffIteratorNodesHandler(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
currentVNode: Array<VNode> | null,
|
firstChild: VNode | null,
|
||||||
newChildrenIterable: Iterable<any>,
|
newChildrenIterable: Iterable<any>,
|
||||||
isComparing: boolean = true
|
isComparing: boolean = true
|
||||||
): Array<VNode> | null {
|
): VNode | null {
|
||||||
const iteratorFn = getIteratorFn(newChildrenIterable);
|
const iteratorFn = getIteratorFn(newChildrenIterable);
|
||||||
const iteratorObj = iteratorFn.call(newChildrenIterable);
|
const iteratorObj = iteratorFn.call(newChildrenIterable);
|
||||||
|
|
||||||
|
@ -381,13 +428,12 @@ function diffIteratorNodesHandler(
|
||||||
result = iteratorObj.next();
|
result = iteratorObj.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
return diffArrayNodes(parentNode, currentVNode, childrenArray, isComparing);
|
return diffArrayNodes(parentNode, firstChild, childrenArray, isComparing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新节点是字符串类型
|
// 新节点是字符串类型
|
||||||
function diffStringNodeHandler(
|
function diffStringNodeHandler(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
currentChildren: Array<VNode> | null,
|
|
||||||
newChild: any,
|
newChild: any,
|
||||||
firstChildVNode: VNode,
|
firstChildVNode: VNode,
|
||||||
isComparing: boolean
|
isComparing: boolean
|
||||||
|
@ -397,10 +443,11 @@ function diffStringNodeHandler(
|
||||||
// 第一个vNode是Text,则复用
|
// 第一个vNode是Text,则复用
|
||||||
if (firstChildVNode !== null && firstChildVNode.tag === DomText) {
|
if (firstChildVNode !== null && firstChildVNode.tag === DomText) {
|
||||||
newTextNode = updateVNode(firstChildVNode, String(newChild));
|
newTextNode = updateVNode(firstChildVNode, String(newChild));
|
||||||
deleteVNodes(parentNode, currentChildren, 1);
|
deleteVNodes(parentNode, firstChildVNode.next);
|
||||||
|
newTextNode.next = null;
|
||||||
} else {
|
} else {
|
||||||
newTextNode = createVNode(DomText, String(newChild));
|
newTextNode = createVNode(DomText, String(newChild));
|
||||||
deleteVNodes(parentNode, currentChildren, 0);
|
deleteVNodes(parentNode, firstChildVNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isComparing && newTextNode.isCreated) {
|
if (isComparing && newTextNode.isCreated) {
|
||||||
|
@ -410,13 +457,13 @@ function diffStringNodeHandler(
|
||||||
newTextNode.cIndex = 0;
|
newTextNode.cIndex = 0;
|
||||||
updateVNodePath(newTextNode);
|
updateVNodePath(newTextNode);
|
||||||
|
|
||||||
return [newTextNode];
|
return newTextNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新节点是对象类型
|
// 新节点是对象类型
|
||||||
function diffObjectNodeHandler(
|
function diffObjectNodeHandler(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
currentChildren: Array<VNode> | null,
|
firstChild: VNode | null,
|
||||||
newChild: any,
|
newChild: any,
|
||||||
firstChildVNode: VNode,
|
firstChildVNode: VNode,
|
||||||
isComparing: boolean
|
isComparing: boolean
|
||||||
|
@ -425,13 +472,14 @@ function diffObjectNodeHandler(
|
||||||
|
|
||||||
// 通过key比对是否有可以reuse
|
// 通过key比对是否有可以reuse
|
||||||
const newKey = newChild.key;
|
const newKey = newChild.key;
|
||||||
for (let i = 0; i < currentChildren.length; i++) {
|
let node = firstChild;
|
||||||
const oldNode = currentChildren[i];
|
while (node !== null) {
|
||||||
if (oldNode.key === newKey) {
|
if (node.key === newKey) {
|
||||||
canReuseNode = oldNode;
|
canReuseNode = node;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
deleteVNode(parentNode, oldNode);
|
deleteVNode(parentNode, node);
|
||||||
|
node = node.next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,10 +491,12 @@ function diffObjectNodeHandler(
|
||||||
if (canReuseNode.tag === Fragment && newChild.type === TYPE_FRAGMENT) {
|
if (canReuseNode.tag === Fragment && newChild.type === TYPE_FRAGMENT) {
|
||||||
resultNode = updateVNode(canReuseNode, newChild.props.children);
|
resultNode = updateVNode(canReuseNode, newChild.props.children);
|
||||||
startDelVNode = getSiblingVNode(canReuseNode);
|
startDelVNode = getSiblingVNode(canReuseNode);
|
||||||
|
resultNode.next = null;
|
||||||
} else if (isSameType(canReuseNode, newChild)) {
|
} else if (isSameType(canReuseNode, newChild)) {
|
||||||
resultNode = updateVNode(canReuseNode, newChild.props);
|
resultNode = updateVNode(canReuseNode, newChild.props);
|
||||||
resultNode.ref = createRef(newChild);
|
resultNode.ref = createRef(newChild);
|
||||||
startDelVNode = getSiblingVNode(canReuseNode);
|
startDelVNode = getSiblingVNode(resultNode);
|
||||||
|
resultNode.next = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,6 +515,7 @@ function diffObjectNodeHandler(
|
||||||
if (canReuseNode.tag === DomPortal && canReuseNode.outerDom === newChild.outerDom) {
|
if (canReuseNode.tag === DomPortal && canReuseNode.outerDom === newChild.outerDom) {
|
||||||
resultNode = updateVNode(canReuseNode, newChild.children || []);
|
resultNode = updateVNode(canReuseNode, newChild.children || []);
|
||||||
startDelVNode = getSiblingVNode(canReuseNode);
|
startDelVNode = getSiblingVNode(canReuseNode);
|
||||||
|
resultNode.next = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (resultNode === null) {
|
if (resultNode === null) {
|
||||||
|
@ -482,9 +533,9 @@ function diffObjectNodeHandler(
|
||||||
resultNode.cIndex = 0;
|
resultNode.cIndex = 0;
|
||||||
updateVNodePath(resultNode);
|
updateVNodePath(resultNode);
|
||||||
if (startDelVNode) {
|
if (startDelVNode) {
|
||||||
deleteVNodes(parentNode, currentChildren, startDelVNode.cIndex);
|
deleteVNodes(parentNode, startDelVNode);
|
||||||
}
|
}
|
||||||
return [resultNode];
|
return resultNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -493,48 +544,47 @@ function diffObjectNodeHandler(
|
||||||
// Diff算法的对外接口
|
// Diff算法的对外接口
|
||||||
export function createChildrenByDiff(
|
export function createChildrenByDiff(
|
||||||
parentNode: VNode,
|
parentNode: VNode,
|
||||||
currentChildren: Array<VNode> | null,
|
firstChild: VNode | null,
|
||||||
newChild: any,
|
newChild: any,
|
||||||
isComparing: boolean = true
|
isComparing: boolean = true
|
||||||
): Array<VNode> | null {
|
): VNode | null {
|
||||||
const isFragment = isNoKeyFragment(newChild);
|
const isFragment = isNoKeyFragment(newChild);
|
||||||
newChild = isFragment ? newChild.props.children : newChild;
|
newChild = isFragment ? newChild.props.children : newChild;
|
||||||
|
|
||||||
// 1. 没有新节点,直接把vNode标记为删除
|
// 1. 没有新节点,直接把vNode标记为删除
|
||||||
if (newChild == null) {
|
if (newChild == null) {
|
||||||
if (isComparing) {
|
if (isComparing) {
|
||||||
deleteVNodes(parentNode, currentChildren, 0);
|
deleteVNodes(parentNode, firstChild);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstChildVNode = currentChildren.length ? currentChildren[0] : null;
|
|
||||||
// 2. newChild是字串类型
|
// 2. newChild是字串类型
|
||||||
if (isTextType(newChild)) {
|
if (isTextType(newChild)) {
|
||||||
return diffStringNodeHandler(parentNode, currentChildren, newChild, firstChildVNode, isComparing);
|
return diffStringNodeHandler(parentNode, newChild, firstChild, isComparing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. newChild是数组类型
|
// 3. newChild是数组类型
|
||||||
if (isArrayType(newChild)) {
|
if (isArrayType(newChild)) {
|
||||||
return diffArrayNodesHandler(parentNode, currentChildren, newChild, isComparing);
|
return diffArrayNodesHandler(parentNode, firstChild, newChild, isComparing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. newChild是迭代器类型
|
// 4. newChild是迭代器类型
|
||||||
if (isIteratorType(newChild)) {
|
if (isIteratorType(newChild)) {
|
||||||
return diffIteratorNodesHandler(parentNode, currentChildren, newChild, isComparing);
|
return diffIteratorNodesHandler(parentNode, firstChild, newChild, isComparing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. newChild是对象类型
|
// 5. newChild是对象类型
|
||||||
if (isObjectType(newChild)) {
|
if (isObjectType(newChild)) {
|
||||||
const newVNodes = diffObjectNodeHandler(parentNode, currentChildren, newChild, firstChildVNode, isComparing);
|
const newVNodes = diffObjectNodeHandler(parentNode, firstChild, newChild, firstChild, isComparing);
|
||||||
if (newVNodes) {
|
if (newVNodes) {
|
||||||
return newVNodes;
|
return newVNodes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. 其它情况删除所有节点
|
// 6. 其它情况删除所有节点
|
||||||
if (firstChildVNode) {
|
if (firstChild) {
|
||||||
deleteVNodes(parentNode, currentChildren, firstChildVNode.cIndex);
|
deleteVNodes(parentNode, firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { createChildrenByDiff } from '../diff/nodeDiffComparator';
|
||||||
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
|
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
|
||||||
import componentRenders from './index';
|
import componentRenders from './index';
|
||||||
|
|
||||||
export function captureVNode(processing: VNode): Array<VNode> | VNode | null {
|
export function captureVNode(processing: VNode): VNode | null {
|
||||||
const component = componentRenders[processing.tag];
|
const component = componentRenders[processing.tag];
|
||||||
|
|
||||||
if (processing.tag !== SuspenseComponent) {
|
if (processing.tag !== SuspenseComponent) {
|
||||||
|
@ -65,10 +65,9 @@ function handlerContext(processing: VNode) {
|
||||||
|
|
||||||
// 创建孩子节点
|
// 创建孩子节点
|
||||||
export function createVNodeChildren(processing: VNode, nextChildren: any) {
|
export function createVNodeChildren(processing: VNode, nextChildren: any) {
|
||||||
const currentChildren = !processing.isCreated ? (processing.children ?? []) : [];
|
|
||||||
const isComparing = !processing.isCreated;
|
const isComparing = !processing.isCreated;
|
||||||
|
|
||||||
return createChildrenByDiff(processing, currentChildren, nextChildren, isComparing);
|
return createChildrenByDiff(processing, processing.child, nextChildren, isComparing);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function markRef(processing: VNode) {
|
export function markRef(processing: VNode) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ import { getContextChangeCtx, setContextChangeCtx } from '../ContextSaver';
|
||||||
import ProcessingVNode from '../vnode/ProcessingVNode';
|
import ProcessingVNode from '../vnode/ProcessingVNode';
|
||||||
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
|
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
|
||||||
|
|
||||||
export function captureRender(processing: VNode): Array<VNode> | null {
|
export function captureRender(processing: VNode): VNode | null {
|
||||||
const clazz = processing.type;
|
const clazz = processing.type;
|
||||||
const props = processing.props;
|
const props = processing.props;
|
||||||
const nextProps = processing.isLazyComponent ? mergeDefaultProps(clazz, props) : props;
|
const nextProps = processing.isLazyComponent ? mergeDefaultProps(clazz, props) : props;
|
||||||
|
@ -44,13 +44,13 @@ export function bubbleRender(processing: VNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用于未完成的类组件
|
// 用于未完成的类组件
|
||||||
export function getIncompleteClassComponent(clazz, processing: VNode, nextProps: object): Array<VNode> | null {
|
export function getIncompleteClassComponent(clazz, processing: VNode, nextProps: object):VNode | null {
|
||||||
mountInstance(clazz, processing, nextProps);
|
mountInstance(clazz, processing, nextProps);
|
||||||
return createChildren(clazz, processing);
|
return createChildren(clazz, processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用于类组件
|
// 用于类组件
|
||||||
export function captureClassComponent(processing: VNode, clazz: any, nextProps: object): Array<VNode> | null {
|
export function captureClassComponent(processing: VNode, clazz: any, nextProps: object): VNode | null {
|
||||||
const isOldCxtExist = isOldProvider(clazz);
|
const isOldCxtExist = isOldProvider(clazz);
|
||||||
cacheOldCtx(processing, isOldCxtExist);
|
cacheOldCtx(processing, isOldCxtExist);
|
||||||
|
|
||||||
|
@ -169,8 +169,8 @@ function createChildren(clazz: any, processing: VNode) {
|
||||||
? null
|
? null
|
||||||
: inst.render();
|
: inst.render();
|
||||||
|
|
||||||
processing.children = createVNodeChildren(processing, newElements);
|
processing.child = createVNodeChildren(processing, newElements);
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前节点的context
|
// 获取当前节点的context
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {FlagUtils} from '../vnode/VNodeFlags';
|
||||||
import {exeFunctionHook} from '../hooks/HookMain';
|
import {exeFunctionHook} from '../hooks/HookMain';
|
||||||
import {createVNodeChildren} from './BaseComponent';
|
import {createVNodeChildren} from './BaseComponent';
|
||||||
|
|
||||||
export function captureRender(processing: VNode): Array<VNode> | null {
|
export function captureRender(processing: VNode): VNode | null {
|
||||||
return captureIndeterminateComponent(processing);
|
return captureIndeterminateComponent(processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ export function bubbleRender() {}
|
||||||
|
|
||||||
function captureIndeterminateComponent(
|
function captureIndeterminateComponent(
|
||||||
processing: VNode | null,
|
processing: VNode | null,
|
||||||
): Array<VNode> | null {
|
): VNode | null {
|
||||||
const funcComp = processing.type;
|
const funcComp = processing.type;
|
||||||
|
|
||||||
if (!processing.isCreated) {
|
if (!processing.isCreated) {
|
||||||
|
@ -31,6 +31,6 @@ function captureIndeterminateComponent(
|
||||||
const newElements = exeFunctionHook(funcComp, props, context, processing);
|
const newElements = exeFunctionHook(funcComp, props, context, processing);
|
||||||
|
|
||||||
processing.tag = FunctionComponent;
|
processing.tag = FunctionComponent;
|
||||||
processing.children = createVNodeChildren(processing, newElements);
|
processing.child = createVNodeChildren(processing, newElements);
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import type {VNode, ContextType} from '../Types';
|
||||||
import {resetDepContexts, getNewContext} from '../components/context/Context';
|
import {resetDepContexts, getNewContext} from '../components/context/Context';
|
||||||
import {createVNodeChildren} from './BaseComponent';
|
import {createVNodeChildren} from './BaseComponent';
|
||||||
|
|
||||||
export function captureRender(processing: VNode): Array<VNode> | null {
|
export function captureRender(processing: VNode): VNode | null {
|
||||||
return captureContextConsumer(processing);
|
return captureContextConsumer(processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,6 @@ function captureContextConsumer(processing: VNode) {
|
||||||
const contextVal = getNewContext(processing, context);
|
const contextVal = getNewContext(processing, context);
|
||||||
const newChildren = renderFunc(contextVal);
|
const newChildren = renderFunc(contextVal);
|
||||||
|
|
||||||
processing.children = createVNodeChildren(processing, newChildren);
|
processing.child = createVNodeChildren(processing, newChildren);
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {launchUpdateFromVNode} from '../TreeBuilder';
|
||||||
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
|
import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
|
||||||
import {setParentsChildShouldUpdate} from '../vnode/VNodeShouldUpdate';
|
import {setParentsChildShouldUpdate} from '../vnode/VNodeShouldUpdate';
|
||||||
|
|
||||||
export function captureRender(processing: VNode): Array<VNode> | null {
|
export function captureRender(processing: VNode): VNode | null {
|
||||||
return captureContextProvider(processing);
|
return captureContextProvider(processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ export function bubbleRender(processing: VNode) {
|
||||||
resetContextCtx(processing);
|
resetContextCtx(processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
function captureContextProvider(processing: VNode): Array<VNode> | null {
|
function captureContextProvider(processing: VNode): VNode | null {
|
||||||
const providerType: ProviderType<any> = processing.type;
|
const providerType: ProviderType<any> = processing.type;
|
||||||
const contextType: ContextType<any> = providerType._context;
|
const contextType: ContextType<any> = providerType._context;
|
||||||
|
|
||||||
|
@ -50,8 +50,8 @@ function captureContextProvider(processing: VNode): Array<VNode> | null {
|
||||||
}
|
}
|
||||||
|
|
||||||
const newElements = newProps.children;
|
const newElements = newProps.children;
|
||||||
processing.children = createVNodeChildren(processing, newElements);
|
processing.child = createVNodeChildren(processing, newElements);
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从依赖中找到匹配context的VNode
|
// 从依赖中找到匹配context的VNode
|
||||||
|
@ -80,7 +80,7 @@ function matchDependencies(depContexts, context, vNode): boolean {
|
||||||
|
|
||||||
// 从当前子节点开始向下遍历,找到消费此context的组件,并更新
|
// 从当前子节点开始向下遍历,找到消费此context的组件,并更新
|
||||||
function handleContextChange(processing: VNode, context: ContextType<any>): void {
|
function handleContextChange(processing: VNode, context: ContextType<any>): void {
|
||||||
const vNode = getFirstChild(processing);
|
const vNode = processing.child;
|
||||||
if (vNode === null) {
|
if (vNode === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {createVNodeChildren, markRef} from './BaseComponent';
|
||||||
import {DomComponent, DomPortal, DomText} from '../vnode/VNodeTags';
|
import {DomComponent, DomPortal, DomText} from '../vnode/VNodeTags';
|
||||||
import {getFirstChild, travelVNodeTree} from '../vnode/VNodeUtils';
|
import {getFirstChild, travelVNodeTree} from '../vnode/VNodeUtils';
|
||||||
|
|
||||||
export function captureRender(processing: VNode): Array<VNode> | null {
|
export function captureRender(processing: VNode): VNode | null {
|
||||||
return captureDomComponent(processing);
|
return captureDomComponent(processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ export function bubbleRender(processing: VNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function captureDomComponent(processing: VNode): Array<VNode> | null {
|
function captureDomComponent(processing: VNode): VNode | null {
|
||||||
setNamespaceCtx(processing);
|
setNamespaceCtx(processing);
|
||||||
|
|
||||||
const type = processing.type;
|
const type = processing.type;
|
||||||
|
@ -82,13 +82,13 @@ function captureDomComponent(processing: VNode): Array<VNode> | null {
|
||||||
}
|
}
|
||||||
|
|
||||||
markRef(processing);
|
markRef(processing);
|
||||||
processing.children = createVNodeChildren(processing, nextChildren);
|
processing.child = createVNodeChildren(processing, nextChildren);
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 把dom类型的子节点append到parent dom中
|
// 把dom类型的子节点append到parent dom中
|
||||||
function appendAllChildren(parent: Element, processing: VNode) {
|
function appendAllChildren(parent: Element, processing: VNode) {
|
||||||
const vNode = getFirstChild(processing);
|
const vNode = processing.child;
|
||||||
if (vNode === null) {
|
if (vNode === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ function updateDom(
|
||||||
);
|
);
|
||||||
processing.changeList = changeList;
|
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);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { createChildrenByDiff } from '../diff/nodeDiffComparator';
|
||||||
import { createVNodeChildren } from './BaseComponent';
|
import { createVNodeChildren } from './BaseComponent';
|
||||||
import { prePortal } from '../../dom/DOMOperator';
|
import { prePortal } from '../../dom/DOMOperator';
|
||||||
|
|
||||||
export function captureRender(processing: VNode): Array<VNode> | null {
|
export function captureRender(processing: VNode): VNode | null {
|
||||||
return capturePortalComponent(processing);
|
return capturePortalComponent(processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ function capturePortalComponent(processing: VNode) {
|
||||||
|
|
||||||
const newElements = processing.props;
|
const newElements = processing.props;
|
||||||
if (processing.isCreated) {
|
if (processing.isCreated) {
|
||||||
processing.children = createChildrenByDiff(processing, [], newElements);
|
processing.child = createChildrenByDiff(processing, null, newElements);
|
||||||
} else {
|
} else {
|
||||||
processing.children = createVNodeChildren(processing, newElements);
|
processing.child = createVNodeChildren(processing, newElements);
|
||||||
}
|
}
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type {VNode} from '../Types';
|
import type {VNode} from '../Types';
|
||||||
import {captureRender as funCaptureRender} from './FunctionComponent';
|
import {captureRender as funCaptureRender} from './FunctionComponent';
|
||||||
|
|
||||||
export function captureRender(processing: VNode, shouldUpdate?: boolean): Array<VNode> | null {
|
export function captureRender(processing: VNode, shouldUpdate?: boolean): VNode | null {
|
||||||
return funCaptureRender(processing, shouldUpdate);
|
return funCaptureRender(processing, shouldUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type {VNode} from '../Types';
|
import type {VNode} from '../Types';
|
||||||
import {createVNodeChildren} from './BaseComponent';
|
import {createVNodeChildren} from './BaseComponent';
|
||||||
|
|
||||||
export function captureRender(processing: VNode): Array<VNode> | null {
|
export function captureRender(processing: VNode): VNode | null {
|
||||||
return captureFragment(processing);
|
return captureFragment(processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,6 @@ export function bubbleRender() {}
|
||||||
|
|
||||||
function captureFragment(processing: VNode) {
|
function captureFragment(processing: VNode) {
|
||||||
const newElement = processing.props;
|
const newElement = processing.props;
|
||||||
processing.children = createVNodeChildren(processing, newElement);
|
processing.child = createVNodeChildren(processing, newElement);
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {onlyUpdateChildVNodes} from '../vnode/VNodeCreator';
|
||||||
// 在useState, useReducer的时候,会触发state变化
|
// 在useState, useReducer的时候,会触发state变化
|
||||||
let stateChange = false;
|
let stateChange = false;
|
||||||
|
|
||||||
export function captureRender(processing: VNode, shouldUpdate?: boolean): Array<VNode> | null {
|
export function captureRender(processing: VNode, shouldUpdate?: boolean): VNode | null {
|
||||||
const Component = processing.type;
|
const Component = processing.type;
|
||||||
const unresolvedProps = processing.props;
|
const unresolvedProps = processing.props;
|
||||||
const resolvedProps =
|
const resolvedProps =
|
||||||
|
@ -62,8 +62,8 @@ export function captureFunctionComponent(
|
||||||
return onlyUpdateChildVNodes(processing);
|
return onlyUpdateChildVNodes(processing);
|
||||||
}
|
}
|
||||||
|
|
||||||
processing.children = createVNodeChildren(processing, newElements);
|
processing.child = createVNodeChildren(processing, newElements);
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断children是否可以复用
|
// 判断children是否可以复用
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from '../utils/elementType';
|
} from '../utils/elementType';
|
||||||
import {Fragment} from '../vnode/VNodeTags';
|
import {Fragment} from '../vnode/VNodeTags';
|
||||||
|
|
||||||
export function captureRender(processing: VNode, shouldUpdate: boolean): Array<VNode> | null {
|
export function captureRender(processing: VNode, shouldUpdate: boolean): VNode | null {
|
||||||
return captureMemoComponent(processing, shouldUpdate);
|
return captureMemoComponent(processing, shouldUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ export function bubbleRender() {}
|
||||||
export function captureMemoComponent(
|
export function captureMemoComponent(
|
||||||
processing: VNode,
|
processing: VNode,
|
||||||
shouldUpdate: boolean,
|
shouldUpdate: boolean,
|
||||||
): Array<VNode> | null {
|
): VNode | null {
|
||||||
const Component = processing.type;
|
const Component = processing.type;
|
||||||
// 合并 函数组件或类组件 的defaultProps
|
// 合并 函数组件或类组件 的defaultProps
|
||||||
const newProps = mergeDefaultProps(Component, processing.props);
|
const newProps = mergeDefaultProps(Component, processing.props);
|
||||||
|
@ -35,12 +35,12 @@ export function captureMemoComponent(
|
||||||
newChild.parent = processing;
|
newChild.parent = processing;
|
||||||
newChild.ref = processing.ref;
|
newChild.ref = processing.ref;
|
||||||
updateVNodePath(newChild);
|
updateVNodePath(newChild);
|
||||||
processing.children = [newChild];
|
processing.child = newChild;
|
||||||
|
|
||||||
return processing.children;
|
return newChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstChild = processing.children.length ? processing.children[0] : null; // Memo只有一个child
|
const firstChild = processing.child; // Memo只有一个child
|
||||||
if (!shouldUpdate) {
|
if (!shouldUpdate) {
|
||||||
const oldProps = firstChild.props;
|
const oldProps = firstChild.props;
|
||||||
// 默认是浅对比
|
// 默认是浅对比
|
||||||
|
@ -55,7 +55,7 @@ export function captureMemoComponent(
|
||||||
newChild.cIndex = 0;
|
newChild.cIndex = 0;
|
||||||
updateVNodePath(newChild);
|
updateVNodePath(newChild);
|
||||||
newChild.ref = processing.ref;
|
newChild.ref = processing.ref;
|
||||||
processing.children = [newChild];
|
processing.child = newChild;
|
||||||
|
|
||||||
return processing.children;
|
return newChild;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ export function captureRender(processing: VNode, shouldUpdate: boolean): Array<V
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFallback(processing: VNode): Array<VNode> | VNode | null {
|
function updateFallback(processing: VNode): Array<VNode> | VNode | null {
|
||||||
const childFragment: VNode = processing.children[0];
|
const childFragment: VNode = processing.child;
|
||||||
|
|
||||||
if (childFragment.childShouldUpdate) {
|
if (childFragment.childShouldUpdate) {
|
||||||
if (processing.promiseResolve) {
|
if (processing.promiseResolve) {
|
||||||
|
@ -45,7 +45,7 @@ function updateFallback(processing: VNode): Array<VNode> | VNode | null {
|
||||||
return captureSuspenseComponent(processing);
|
return captureSuspenseComponent(processing);
|
||||||
} else {
|
} else {
|
||||||
// promise未完成,继续显示fallback,不需要继续刷新子节点
|
// promise未完成,继续显示fallback,不需要继续刷新子节点
|
||||||
const fallbackFragment: VNode = processing.children[1];
|
const fallbackFragment: VNode = processing.child.next;
|
||||||
childFragment.childShouldUpdate = false;
|
childFragment.childShouldUpdate = false;
|
||||||
fallbackFragment.childShouldUpdate = false;
|
fallbackFragment.childShouldUpdate = false;
|
||||||
return null;
|
return null;
|
||||||
|
@ -92,10 +92,11 @@ export function captureSuspenseComponent(processing: VNode) {
|
||||||
function createSuspenseChildren(processing: VNode, newChildren) {
|
function createSuspenseChildren(processing: VNode, newChildren) {
|
||||||
let childFragment: VNode;
|
let childFragment: VNode;
|
||||||
if (!processing.isCreated) {
|
if (!processing.isCreated) {
|
||||||
const oldChildFragment: VNode = processing.children[0];
|
const oldChildFragment: VNode = processing.child;
|
||||||
const oldFallbackFragment: VNode | null = processing.children.length > 1 ? processing.children[1] : null;
|
const oldFallbackFragment: VNode | null = oldChildFragment.next;
|
||||||
|
|
||||||
childFragment = updateVNode(oldChildFragment);
|
childFragment = updateVNode(oldChildFragment);
|
||||||
|
childFragment.next = null;
|
||||||
// 将Suspense新的子参数传给子Fragment
|
// 将Suspense新的子参数传给子Fragment
|
||||||
childFragment.props = processing.props.children;
|
childFragment.props = processing.props.children;
|
||||||
childFragment.shouldUpdate = true;
|
childFragment.shouldUpdate = true;
|
||||||
|
@ -114,19 +115,19 @@ function createSuspenseChildren(processing: VNode, newChildren) {
|
||||||
childFragment.parent = processing;
|
childFragment.parent = processing;
|
||||||
childFragment.cIndex = 0;
|
childFragment.cIndex = 0;
|
||||||
updateVNodePath(childFragment);
|
updateVNodePath(childFragment);
|
||||||
processing.children = [childFragment];
|
processing.child = childFragment;
|
||||||
processing.promiseResolve = false;
|
processing.promiseResolve = false;
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建fallback子节点
|
// 创建fallback子节点
|
||||||
function createFallback(processing: VNode, fallbackChildren) {
|
function createFallback(processing: VNode, fallbackChildren) {
|
||||||
const childFragment: VNode = processing.children[0];
|
const childFragment: VNode = processing.child;
|
||||||
let fallbackFragment;
|
let fallbackFragment;
|
||||||
childFragment.childShouldUpdate = false;
|
childFragment.childShouldUpdate = false;
|
||||||
|
|
||||||
if (!processing.isCreated) {
|
if (!processing.isCreated) {
|
||||||
const oldFallbackFragment: VNode | null = processing.oldChildren.length > 1 ? processing.oldChildren[1] : null;
|
const oldFallbackFragment: VNode | null = processing.oldChild ? processing.oldChild.next : null;
|
||||||
|
|
||||||
if (oldFallbackFragment !== null) {
|
if (oldFallbackFragment !== null) {
|
||||||
fallbackFragment = updateVNode(oldFallbackFragment, fallbackChildren);
|
fallbackFragment = updateVNode(oldFallbackFragment, fallbackChildren);
|
||||||
|
@ -139,7 +140,8 @@ function createFallback(processing: VNode, fallbackChildren) {
|
||||||
fallbackFragment = createVNode(Fragment, null, fallbackChildren);
|
fallbackFragment = createVNode(Fragment, null, fallbackChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
processing.children = [childFragment, fallbackFragment];
|
processing.child = childFragment;
|
||||||
|
childFragment.next = fallbackFragment;
|
||||||
childFragment.parent = processing;
|
childFragment.parent = processing;
|
||||||
fallbackFragment.parent = processing;
|
fallbackFragment.parent = processing;
|
||||||
fallbackFragment.eIndex = 1;
|
fallbackFragment.eIndex = 1;
|
||||||
|
@ -147,7 +149,7 @@ function createFallback(processing: VNode, fallbackChildren) {
|
||||||
updateVNodePath(fallbackFragment);
|
updateVNodePath(fallbackFragment);
|
||||||
processing.suspenseChildStatus = SuspenseChildStatus.ShowFallback;
|
processing.suspenseChildStatus = SuspenseChildStatus.ShowFallback;
|
||||||
|
|
||||||
return [fallbackFragment];
|
return fallbackFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理Suspense子组件抛出的promise
|
// 处理Suspense子组件抛出的promise
|
||||||
|
|
|
@ -37,6 +37,6 @@ function updateTreeRoot(processing) {
|
||||||
if (newElement === oldElement) {
|
if (newElement === oldElement) {
|
||||||
return onlyUpdateChildVNodes(processing);
|
return onlyUpdateChildVNodes(processing);
|
||||||
}
|
}
|
||||||
processing.children = createVNodeChildren(processing, newElement);
|
processing.child = createVNodeChildren(processing, newElement);
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,8 +124,7 @@ function callAfterSubmitLifeCycles(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case TreeRoot: {
|
case TreeRoot: {
|
||||||
const childVNode = (vNode.children && vNode.children.length) ? vNode.children[0] : null;
|
const instance = vNode.child !== null ? vNode.child.realNode : null;
|
||||||
const instance = childVNode !== null ? childVNode.realNode : null;
|
|
||||||
callStateCallback(vNode, instance);
|
callStateCallback(vNode, instance);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -261,10 +260,11 @@ function insertOrAppendPlacementNode(
|
||||||
// 这里不做处理,直接在portal中处理
|
// 这里不做处理,直接在portal中处理
|
||||||
} else {
|
} else {
|
||||||
// 插入子节点们
|
// 插入子节点们
|
||||||
const children = node.children || [];
|
let child = node.child;
|
||||||
children.forEach(child => {
|
while (child !== null) {
|
||||||
insertOrAppendPlacementNode(child, beforeDom, parent);
|
insertOrAppendPlacementNode(child, beforeDom, parent);
|
||||||
});
|
child = child.next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ function unmountDomComponents(vNode: VNode): void {
|
||||||
// 在所有子项都卸载后,删除dom树中的节点
|
// 在所有子项都卸载后,删除dom树中的节点
|
||||||
removeChildDom(currentParent, node.realNode);
|
removeChildDom(currentParent, node.realNode);
|
||||||
} else if (node.tag === DomPortal) {
|
} else if (node.tag === DomPortal) {
|
||||||
if (node.children.length) {
|
if (node.child !== null) {
|
||||||
currentParent = node.outerDom;
|
currentParent = node.outerDom;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -336,10 +336,10 @@ function submitUpdate(vNode: VNode): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitSuspenseComponent(finishedWork: VNode) {
|
function submitSuspenseComponent(vNode: VNode) {
|
||||||
const suspenseChildStatus = finishedWork.suspenseChildStatus;
|
const suspenseChildStatus = vNode.suspenseChildStatus;
|
||||||
if (suspenseChildStatus !== SuspenseChildStatus.Init) {
|
if (suspenseChildStatus !== SuspenseChildStatus.Init) {
|
||||||
hideOrUnhideAllChildren(finishedWork.children[0], suspenseChildStatus === SuspenseChildStatus.ShowFallback);
|
hideOrUnhideAllChildren(vNode.child, suspenseChildStatus === SuspenseChildStatus.ShowFallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,7 @@ export function clearDirtyNodes(dirtyNodes) {
|
||||||
dirtyNodes.forEach(node => {
|
dirtyNodes.forEach(node => {
|
||||||
if (node.flags.Deletion) {
|
if (node.flags.Deletion) {
|
||||||
node.realNode = null;
|
node.realNode = null;
|
||||||
|
node.next = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,8 @@ export class VNode {
|
||||||
|
|
||||||
// 关系结构
|
// 关系结构
|
||||||
parent: VNode | null = null; // 父节点
|
parent: VNode | null = null; // 父节点
|
||||||
children: Array<VNode> | null = null; // 子节点
|
child: VNode | null = null; // 子节点
|
||||||
|
next: VNode | null = null; // 兄弟节点
|
||||||
cIndex: number = 0; // 节点在children数组中的位置
|
cIndex: number = 0; // 节点在children数组中的位置
|
||||||
eIndex: number = 0; // HorizonElement在jsx中的位置,例如:jsx中的null不会生成vNode,所以eIndex和cIndex不一致
|
eIndex: number = 0; // HorizonElement在jsx中的位置,例如:jsx中的null不会生成vNode,所以eIndex和cIndex不一致
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ export class VNode {
|
||||||
oldRef: RefType | ((handle: any) => void) | null = null;
|
oldRef: RefType | ((handle: any) => void) | null = null;
|
||||||
suspenseChildThrow = false;
|
suspenseChildThrow = false;
|
||||||
oldSuspenseChildStatus: string = ''; // 上一次Suspense的Children是否显示
|
oldSuspenseChildStatus: string = ''; // 上一次Suspense的Children是否显示
|
||||||
oldChildren: Array<VNode> | null = null;
|
oldChild: VNode | null = null;
|
||||||
suspenseDidCapture: boolean = false; // suspense是否捕获了异常
|
suspenseDidCapture: boolean = false; // suspense是否捕获了异常
|
||||||
promiseResolve: boolean = false; // suspense的promise是否resolve
|
promiseResolve: boolean = false; // suspense的promise是否resolve
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ export function updateVNode(vNode: VNode, vNodeProps?: any): VNode {
|
||||||
|
|
||||||
if (vNode.tag === SuspenseComponent) {
|
if (vNode.tag === SuspenseComponent) {
|
||||||
vNode.oldSuspenseChildStatus = vNode.suspenseChildStatus;
|
vNode.oldSuspenseChildStatus = vNode.suspenseChildStatus;
|
||||||
vNode.oldChildren = vNode.children;
|
vNode.oldChild = vNode.child;
|
||||||
}
|
}
|
||||||
|
|
||||||
vNode.oldProps = vNode.props;
|
vNode.oldProps = vNode.props;
|
||||||
|
@ -169,20 +169,22 @@ export function createVNodeFromElement(element: HorizonElement): VNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 直接更新子节点属性即可,不需要diff
|
// 直接更新子节点属性即可,不需要diff
|
||||||
export function onlyUpdateChildVNodes(processing: VNode): Array<VNode> | null {
|
export function onlyUpdateChildVNodes(processing: VNode): VNode | null {
|
||||||
// 检查子树是否需要更新
|
// 检查子树是否需要更新
|
||||||
if (processing.childShouldUpdate) {
|
if (processing.childShouldUpdate) {
|
||||||
// 此vNode无需更新,但是子树需要
|
// 此vNode无需更新,但是子树需要
|
||||||
if (!processing.isCreated && processing.children && processing.children.length) {
|
if (!processing.isCreated && processing.child !== null) {
|
||||||
// 更新子节点
|
// 更新子节点
|
||||||
processing.children.forEach(child => {
|
let child = processing.child;
|
||||||
|
while (child !== null) {
|
||||||
updateVNode(child, child.props);
|
updateVNode(child, child.props);
|
||||||
updateVNodePath(child);
|
updateVNodePath(child);
|
||||||
});
|
child = child.next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回子节点,继续遍历
|
// 返回子节点,继续遍历
|
||||||
return processing.children;
|
return processing.child;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 子树无需工作
|
// 子树无需工作
|
||||||
|
|
|
@ -25,15 +25,15 @@ export function updateShouldUpdateOfTree(vNode: VNode): VNode | null {
|
||||||
|
|
||||||
// 设置节点的childShouldUpdate
|
// 设置节点的childShouldUpdate
|
||||||
export function updateChildShouldUpdate(vNode: VNode) {
|
export function updateChildShouldUpdate(vNode: VNode) {
|
||||||
const children = vNode.children || [];
|
let child = vNode.child;
|
||||||
|
while (child !== null) {
|
||||||
for (let i = 0; i < children.length; i++) {
|
if (child.shouldUpdate || child.childShouldUpdate) {
|
||||||
const child = children[i];
|
|
||||||
if (child && (child.shouldUpdate || child.childShouldUpdate)) {
|
|
||||||
vNode.childShouldUpdate = true;
|
vNode.childShouldUpdate = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
child = child.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
vNode.childShouldUpdate = false;
|
vNode.childShouldUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,21 @@ import {isComment} from '../../dom/utils/Common';
|
||||||
import {getNearestVNode} from '../../dom/DOMInternalKeys';
|
import {getNearestVNode} from '../../dom/DOMInternalKeys';
|
||||||
|
|
||||||
export function getSiblingVNode(node) {
|
export function getSiblingVNode(node) {
|
||||||
let siblingVNode = null;
|
return node.next;
|
||||||
const index = node.cIndex;
|
|
||||||
if (node && node.parent && node.parent.children && node.parent.children.length > index + 1) {
|
|
||||||
siblingVNode = node.parent.children[index + 1];
|
|
||||||
}
|
|
||||||
return siblingVNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFirstChild(vNode: VNode) {
|
export function travelChildren(beginVNode: VNode, handleVNode: Function, isFinish?: Function) {
|
||||||
return (vNode.children && vNode.children.length) ? vNode.children[0] : null;
|
let node = beginVNode;
|
||||||
|
|
||||||
|
while (node !== null) {
|
||||||
|
if (isFinish && isFinish(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleVNode(node);
|
||||||
|
|
||||||
|
node = node.next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从beginVNode开始深度遍历vNode树,对每个vNode调用handleVNode方法
|
// 从beginVNode开始深度遍历vNode树,对每个vNode调用handleVNode方法
|
||||||
|
@ -40,7 +45,7 @@ export function travelVNodeTree(
|
||||||
}
|
}
|
||||||
|
|
||||||
// 找子节点
|
// 找子节点
|
||||||
const childVNode = getFirstChild(node);
|
const childVNode = node.child;
|
||||||
if (childVNode !== null && !childFilter(node)) {
|
if (childVNode !== null && !childFilter(node)) {
|
||||||
childVNode.parent = node;
|
childVNode.parent = node;
|
||||||
node = childVNode;
|
node = childVNode;
|
||||||
|
@ -76,7 +81,8 @@ export function clearVNode(vNode: VNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearOneVNode(vNode: VNode) {
|
function clearOneVNode(vNode: VNode) {
|
||||||
vNode.children = [];
|
vNode.child = null;
|
||||||
|
vNode.next = null;
|
||||||
vNode.depContexts = [];
|
vNode.depContexts = [];
|
||||||
vNode.dirtyNodes = [];
|
vNode.dirtyNodes = [];
|
||||||
vNode.oldProps = null;
|
vNode.oldProps = null;
|
||||||
|
@ -95,7 +101,7 @@ function clearOneVNode(vNode: VNode) {
|
||||||
vNode.oldRef = null;
|
vNode.oldRef = null;
|
||||||
vNode.suspenseChildThrow = false;
|
vNode.suspenseChildThrow = false;
|
||||||
vNode.oldSuspenseChildStatus = '';
|
vNode.oldSuspenseChildStatus = '';
|
||||||
vNode.oldChildren = null;
|
vNode.oldChild = null;
|
||||||
|
|
||||||
vNode.path = [];
|
vNode.path = [];
|
||||||
vNode.toUpdateNodes = null;
|
vNode.toUpdateNodes = null;
|
||||||
|
@ -193,10 +199,10 @@ export function getSiblingDom(vNode: VNode): Element | null {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 没有子节点,或是DomPortal
|
// 没有子节点,或是DomPortal
|
||||||
if (!node.children || !node.children.length || node.tag === DomPortal) {
|
if (!node.child || node.tag === DomPortal) {
|
||||||
continue findSibling;
|
continue findSibling;
|
||||||
} else {
|
} else {
|
||||||
const childVNode = getFirstChild(node);
|
const childVNode = node.child;
|
||||||
childVNode.parent = node;
|
childVNode.parent = node;
|
||||||
node = childVNode;
|
node = childVNode;
|
||||||
}
|
}
|
||||||
|
@ -274,5 +280,3 @@ export function getExactNode(targetVNode, targetContainer) {
|
||||||
}
|
}
|
||||||
return targetVNode;
|
return targetVNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue