refactor: move clone step into util function

This commit is contained in:
Evan You 2018-12-01 18:09:21 -05:00
parent 1b40fa6c16
commit 85bcc2b87c

View File

@ -125,7 +125,9 @@ export function createRenderer(options: RendererOptions) {
container: RenderNode | null, container: RenderNode | null,
contextVNode: MountedVNode | null, contextVNode: MountedVNode | null,
isSVG: boolean, isSVG: boolean,
endNode: RenderNode | null endNode: RenderNode | null,
ownerArray?: VNode[],
index?: number
) { ) {
const { flags } = vnode const { flags } = vnode
if (flags & VNodeFlags.ELEMENT) { if (flags & VNodeFlags.ELEMENT) {
@ -149,11 +151,8 @@ export function createRenderer(options: RendererOptions) {
endNode: RenderNode | null endNode: RenderNode | null
) { ) {
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
let child = children[i] const child = getNextVNode(children, i)
if (child.el) { mount(child, container, contextVNode, isSVG, endNode)
children[i] = child = cloneVNode(child)
}
mount(children[i], container, contextVNode, isSVG, endNode)
} }
} }
@ -879,20 +878,14 @@ export function createRenderer(options: RendererOptions) {
let nextChild let nextChild
let prevChild let prevChild
for (i; i < commonLength; i++) { for (i; i < commonLength; i++) {
nextChild = nextChildren[i] nextChild = getNextVNode(nextChildren, i)
prevChild = prevChildren[i] prevChild = prevChildren[i]
if (nextChild.el) {
nextChildren[i] = nextChild = cloneVNode(nextChild)
}
patch(prevChild, nextChild, container, contextVNode, isSVG) patch(prevChild, nextChild, container, contextVNode, isSVG)
prevChildren[i] = nextChild as MountedVNode prevChildren[i] = nextChild as MountedVNode
} }
if (prevLength < nextLength) { if (prevLength < nextLength) {
for (i = commonLength; i < nextLength; i++) { for (i = commonLength; i < nextLength; i++) {
nextChild = nextChildren[i] nextChild = getNextVNode(nextChildren, i)
if (nextChild.el) {
nextChildren[i] = nextChild = cloneVNode(nextChild)
}
mount(nextChild, container, contextVNode, isSVG, endNode) mount(nextChild, container, contextVNode, isSVG, endNode)
} }
} else if (prevLength > nextLength) { } else if (prevLength > nextLength) {
@ -917,15 +910,12 @@ export function createRenderer(options: RendererOptions) {
let i let i
let j = 0 let j = 0
let prevVNode = prevChildren[j] let prevVNode = prevChildren[j]
let nextVNode = nextChildren[j] let nextVNode = getNextVNode(nextChildren, j)
let nextPos let nextPos
outer: { outer: {
// Sync nodes with the same key at the beginning. // Sync nodes with the same key at the beginning.
while (prevVNode.key === nextVNode.key) { while (prevVNode.key === nextVNode.key) {
if (nextVNode.el) {
nextChildren[j] = nextVNode = cloneVNode(nextVNode)
}
patch(prevVNode, nextVNode, container, contextVNode, isSVG) patch(prevVNode, nextVNode, container, contextVNode, isSVG)
prevChildren[j] = nextVNode as MountedVNode prevChildren[j] = nextVNode as MountedVNode
j++ j++
@ -933,17 +923,14 @@ export function createRenderer(options: RendererOptions) {
break outer break outer
} }
prevVNode = prevChildren[j] prevVNode = prevChildren[j]
nextVNode = nextChildren[j] nextVNode = getNextVNode(nextChildren, j)
} }
prevVNode = prevChildren[prevEnd] prevVNode = prevChildren[prevEnd]
nextVNode = nextChildren[nextEnd] nextVNode = getNextVNode(nextChildren, nextEnd)
// Sync nodes with the same key at the end. // Sync nodes with the same key at the end.
while (prevVNode.key === nextVNode.key) { while (prevVNode.key === nextVNode.key) {
if (nextVNode.el) {
nextChildren[nextEnd] = nextVNode = cloneVNode(nextVNode)
}
patch(prevVNode, nextVNode, container, contextVNode, isSVG) patch(prevVNode, nextVNode, container, contextVNode, isSVG)
prevChildren[prevEnd] = nextVNode as MountedVNode prevChildren[prevEnd] = nextVNode as MountedVNode
prevEnd-- prevEnd--
@ -952,7 +939,7 @@ export function createRenderer(options: RendererOptions) {
break outer break outer
} }
prevVNode = prevChildren[prevEnd] prevVNode = prevChildren[prevEnd]
nextVNode = nextChildren[nextEnd] nextVNode = getNextVNode(nextChildren, nextEnd)
} }
} }
@ -962,10 +949,7 @@ export function createRenderer(options: RendererOptions) {
const nextNode = const nextNode =
nextPos < nextLength ? nextChildren[nextPos].el : endNode nextPos < nextLength ? nextChildren[nextPos].el : endNode
while (j <= nextEnd) { while (j <= nextEnd) {
nextVNode = nextChildren[j] nextVNode = getNextVNode(nextChildren, j)
if (nextVNode.el) {
nextChildren[j] = nextVNode = cloneVNode(nextVNode)
}
j++ j++
mount(nextVNode, container, contextVNode, isSVG, nextNode) mount(nextVNode, container, contextVNode, isSVG, nextNode)
} }
@ -995,7 +979,7 @@ export function createRenderer(options: RendererOptions) {
prevVNode = prevChildren[i] prevVNode = prevChildren[i]
if (patched < nextLeft) { if (patched < nextLeft) {
for (j = nextStart; j <= nextEnd; j++) { for (j = nextStart; j <= nextEnd; j++) {
nextVNode = nextChildren[j] nextVNode = getNextVNode(nextChildren, j)
if (prevVNode.key === nextVNode.key) { if (prevVNode.key === nextVNode.key) {
sources[j - nextStart] = i + 1 sources[j - nextStart] = i + 1
if (canRemoveWholeContent) { if (canRemoveWholeContent) {
@ -1009,9 +993,6 @@ export function createRenderer(options: RendererOptions) {
} else { } else {
pos = j pos = j
} }
if (nextVNode.el) {
nextChildren[j] = nextVNode = cloneVNode(nextVNode)
}
patch(prevVNode, nextVNode, container, contextVNode, isSVG) patch(prevVNode, nextVNode, container, contextVNode, isSVG)
patched++ patched++
break break
@ -1046,16 +1027,13 @@ export function createRenderer(options: RendererOptions) {
queueRemoveVNode(prevChildren[prevStart++], container) queueRemoveVNode(prevChildren[prevStart++], container)
} }
} }
nextVNode = nextChildren[j] nextVNode = getNextVNode(nextChildren, j)
sources[j - nextStart] = i + 1 sources[j - nextStart] = i + 1
if (pos > j) { if (pos > j) {
moved = true moved = true
} else { } else {
pos = j pos = j
} }
if (nextVNode.el) {
nextChildren[j] = nextVNode = cloneVNode(nextVNode)
}
patch(prevVNode, nextVNode, container, contextVNode, isSVG) patch(prevVNode, nextVNode, container, contextVNode, isSVG)
patched++ patched++
} else if (!canRemoveWholeContent) { } else if (!canRemoveWholeContent) {
@ -1083,10 +1061,7 @@ export function createRenderer(options: RendererOptions) {
for (i = nextLeft - 1; i >= 0; i--) { for (i = nextLeft - 1; i >= 0; i--) {
if (sources[i] === 0) { if (sources[i] === 0) {
pos = i + nextStart pos = i + nextStart
nextVNode = nextChildren[pos] nextVNode = getNextVNode(nextChildren, pos)
if (nextVNode.el) {
nextChildren[pos] = nextVNode = cloneVNode(nextVNode)
}
nextPos = pos + 1 nextPos = pos + 1
mount( mount(
nextVNode, nextVNode,
@ -1114,10 +1089,7 @@ export function createRenderer(options: RendererOptions) {
for (i = nextLeft - 1; i >= 0; i--) { for (i = nextLeft - 1; i >= 0; i--) {
if (sources[i] === 0) { if (sources[i] === 0) {
pos = i + nextStart pos = i + nextStart
nextVNode = nextChildren[pos] nextVNode = getNextVNode(nextChildren, pos)
if (nextVNode.el) {
nextChildren[pos] = nextVNode = cloneVNode(nextVNode)
}
nextPos = pos + 1 nextPos = pos + 1
mount( mount(
nextVNode, nextVNode,
@ -1589,8 +1561,17 @@ export function createRenderer(options: RendererOptions) {
return { render } return { render }
} }
// Utils -----------------------------------------------------------------------
// retrieves a vnode from a children array, making sure to clone it if the
// vnode is already mounted.
function getNextVNode(ownerArray: VNode[], index: number): VNode {
const vnode = ownerArray[index]
return vnode.el === null ? vnode : (ownerArray[index] = cloneVNode(vnode))
}
// https://en.wikipedia.org/wiki/Longest_increasing_subsequence // https://en.wikipedia.org/wiki/Longest_increasing_subsequence
export function lis(arr: number[]): number[] { function lis(arr: number[]): number[] {
const p = arr.slice() const p = arr.slice()
const result = [0] const result = [0]
let i let i