UNPKG

mostly-dom

Version:
123 lines (98 loc) 4.03 kB
import { ElementVNode } from './types' import { ModuleCallbacks } from './modules/ModuleCallbacks' import { addVNodes } from './addVNodes' import { createElement } from './createElement' import { patchVNode } from './patchVNode' import { removeVNodes } from './removeVNodes' import { vNodesAreEqual } from './helpers' export function updateChildren( parentElement: Element, formerChildren: Array<ElementVNode>, children: Array<ElementVNode>, moduleCallbacks: ModuleCallbacks, insertedVNodeQueue: Array<ElementVNode>) { // indexes let formerStartIndex = 0 let startIndex = 0 let formerEndIndex = formerChildren.length - 1 let endIndex = children.length - 1 // VNodes let formerStartVNode = formerChildren[formerStartIndex] let startVNode = children[startIndex] let formerEndVNode = formerChildren[formerEndIndex] let endVNode = children[endIndex] // an object mapping keys to indexes in formerChildren array let mappedKeyToFormerIndex: any while (formerStartIndex <= formerEndIndex && startIndex <= endIndex) { if (!formerStartVNode) formerStartVNode = formerChildren[++formerStartIndex] else if (!formerEndVNode) formerEndVNode = formerChildren[--formerEndIndex] else if (vNodesAreEqual(formerStartVNode, startVNode)) { patchVNode(formerStartVNode, startVNode, moduleCallbacks, insertedVNodeQueue) formerStartVNode = formerChildren[++formerStartIndex] startVNode = children[++startIndex] } else if (vNodesAreEqual(formerEndVNode, endVNode)) { patchVNode(formerEndVNode, endVNode, moduleCallbacks, insertedVNodeQueue) formerEndVNode = formerChildren[--formerEndIndex] endVNode = children[--endIndex] } else if (vNodesAreEqual(formerStartVNode, endVNode)) { patchVNode(formerStartVNode, endVNode, moduleCallbacks, insertedVNodeQueue) parentElement.insertBefore(formerStartVNode.element, formerEndVNode.element.nextSibling) formerStartVNode = formerChildren[++formerStartIndex] endVNode = children[--endIndex] } else if (vNodesAreEqual(formerEndVNode, startVNode)) { patchVNode(formerEndVNode, startVNode, moduleCallbacks, insertedVNodeQueue) parentElement.insertBefore(formerEndVNode.element, formerStartVNode.element) formerEndVNode = formerChildren[--formerEndIndex] startVNode = children[++startIndex] } else { if (!mappedKeyToFormerIndex) mappedKeyToFormerIndex = mapKeyToFormerIndex(formerChildren, formerStartIndex, formerEndIndex) const formerIndexKey = mappedKeyToFormerIndex[startVNode.key as string | number] if (!formerIndexKey) { // new element const element = createElement(startVNode, moduleCallbacks, insertedVNodeQueue).element parentElement.insertBefore(element, formerStartVNode.element) startVNode = children[++startIndex] } else { const reorderableVNode = formerChildren[formerIndexKey] patchVNode(reorderableVNode, startVNode, moduleCallbacks, insertedVNodeQueue) // WARNING: hack for performance optimization formerChildren[formerIndexKey] = void 0 as any parentElement.insertBefore(reorderableVNode.element, formerStartVNode.element) startVNode = children[++startIndex] } } } if (formerStartIndex > formerEndIndex) { const referenceNode = children[endIndex + 1] ? children[endIndex + 1].element : null addVNodes( parentElement, referenceNode, children, startIndex, endIndex, moduleCallbacks, insertedVNodeQueue, ) } else if (startIndex > endIndex) removeVNodes(parentElement, formerChildren, formerStartIndex, formerEndIndex, moduleCallbacks) } function mapKeyToFormerIndex( children: Array<ElementVNode>, startIndex: number, endIndex: number): any { let index: number = startIndex const map: any = {} let key: any for (; index <= endIndex; ++index) { key = children[index].key if (key) map[key] = index } return map }