diff --git a/src/patch.ts b/src/patch.ts index 3f03f42a7c..cf2316a9b6 100644 --- a/src/patch.ts +++ b/src/patch.ts @@ -47,9 +47,12 @@ export const patchChildren = ( el: HTMLElement, oldVNodeChildren: VNode[], newVNodeChildren: VNode[], + keyed: boolean, delta?: VDelta, ): void => { - if (delta) { + if (!newVNodeChildren) { + el.textContent = ''; + } else if (delta) { for (let i = 0; i < delta.length; i++) { const [deltaType, deltaPosition] = delta[i]; switch (deltaType) { @@ -74,10 +77,12 @@ export const patchChildren = ( } } } - } else if (!newVNodeChildren) { - el.textContent = ''; + } else if (keyed) { + // TODO: Efficient diffing by keys with moves (#107) } else { if (oldVNodeChildren) { + // Interates backwards, so in case a childNode is destroyed, it will not shift the nodes + // and break accessing by index for (let i = oldVNodeChildren.length - 1; i >= 0; --i) { patch(el.childNodes[i], newVNodeChildren[i], oldVNodeChildren[i]); } @@ -136,6 +141,7 @@ export const patch = (el: HTMLElement | Text, newVNode: VNode, prevVNode?: VNode el, (oldVNode)?.children || [], (newVNode).children!, + (newVNode).flag === VFlags.ONLY_KEYED_CHILDREN, // We need to pass delta here because this function does not have // a reference to the actual vnode. (newVNode).delta, diff --git a/src/structs.ts b/src/structs.ts index 69c19c1e30..6ccd54feff 100644 --- a/src/structs.ts +++ b/src/structs.ts @@ -23,6 +23,7 @@ export enum VFlags { NO_CHILDREN = 1 << 0, ONLY_TEXT_CHILDREN = 1 << 1, ANY_CHILDREN = 1 << 2, + ONLY_KEYED_CHILDREN = 1 << 3, } export const enum VDeltaOperationTypes {