MountedVNode,
RenderNode,
createTextVNode,
- cloneVNode,
Ref,
VNodeChildren
} from './vdom'
endNode: RenderNode | null
) {
for (let i = 0; i < children.length; i++) {
- let child = children[i]
- if (child.el) {
- children[i] = child = cloneVNode(child)
- }
mount(children[i], container, contextVNode, isSVG, endNode)
}
}
contextVNode: MountedVNode | null,
isSVG: boolean
) {
+ if (prevVNode === nextVNode) {
+ nextVNode.el = prevVNode.el
+ return
+ }
+
const nextFlags = nextVNode.flags
const prevFlags = prevVNode.flags
for (i; i < commonLength; i++) {
nextChild = nextChildren[i]
prevChild = prevChildren[i]
- if (nextChild.el) {
- nextChildren[i] = nextChild = cloneVNode(nextChild)
- }
patch(prevChild, nextChild, container, contextVNode, isSVG)
prevChildren[i] = nextChild as MountedVNode
}
if (prevLength < nextLength) {
for (i = commonLength; i < nextLength; i++) {
- nextChild = nextChildren[i]
- if (nextChild.el) {
- nextChildren[i] = nextChild = cloneVNode(nextChild)
- }
- mount(nextChild, container, contextVNode, isSVG, endNode)
+ mount(nextChildren[i], container, contextVNode, isSVG, endNode)
}
} else if (prevLength > nextLength) {
for (i = commonLength; i < prevLength; i++) {
outer: {
// Sync nodes with the same key at the beginning.
while (prevVNode.key === nextVNode.key) {
- if (nextVNode.el) {
- nextChildren[j] = nextVNode = cloneVNode(nextVNode)
- }
patch(prevVNode, nextVNode, container, contextVNode, isSVG)
prevChildren[j] = nextVNode as MountedVNode
j++
// Sync nodes with the same key at the end.
while (prevVNode.key === nextVNode.key) {
- if (nextVNode.el) {
- nextChildren[nextEnd] = nextVNode = cloneVNode(nextVNode)
- }
patch(prevVNode, nextVNode, container, contextVNode, isSVG)
prevChildren[prevEnd] = nextVNode as MountedVNode
prevEnd--
const nextNode =
nextPos < nextLength ? nextChildren[nextPos].el : endNode
while (j <= nextEnd) {
- nextVNode = nextChildren[j]
- if (nextVNode.el) {
- nextChildren[j] = nextVNode = cloneVNode(nextVNode)
- }
- j++
+ nextVNode = nextChildren[j++]
mount(nextVNode, container, contextVNode, isSVG, nextNode)
}
}
} else {
pos = j
}
- if (nextVNode.el) {
- nextChildren[j] = nextVNode = cloneVNode(nextVNode)
- }
patch(prevVNode, nextVNode, container, contextVNode, isSVG)
patched++
break
} else {
pos = j
}
- if (nextVNode.el) {
- nextChildren[j] = nextVNode = cloneVNode(nextVNode)
- }
patch(prevVNode, nextVNode, container, contextVNode, isSVG)
patched++
} else if (!canRemoveWholeContent) {
if (sources[i] === 0) {
pos = i + nextStart
nextVNode = nextChildren[pos]
- if (nextVNode.el) {
- nextChildren[pos] = nextVNode = cloneVNode(nextVNode)
- }
nextPos = pos + 1
mount(
nextVNode,
if (sources[i] === 0) {
pos = i + nextStart
nextVNode = nextChildren[pos]
- if (nextVNode.el) {
- nextChildren[pos] = nextVNode = cloneVNode(nextVNode)
- }
nextPos = pos + 1
mount(
nextVNode,
} else {
platformRemoveChild(container, el)
}
- ;(vnode as any).el = null
}
+ ;(vnode as any).el = null
}
function removeChildren(
container: any
): ComponentInstance | null {
const prevVNode = container.vnode
- if (vnode && vnode.el) {
- vnode = cloneVNode(vnode)
- }
if (prevVNode == null) {
if (vnode) {
mount(vnode, container, null, false, null)
--- /dev/null
+// Used for memoizing trees inside render functions.
+//
+// Example (equivalent of v-once):
+//
+// render() {
+// return memoize(h('div', this.msg), this, 0)
+// }
+//
+// Memoize baesd on keys:
+//
+// render() {
+// return memoize(h('div', this.msg + this.count), this, 0, [this.msg])
+// }
+
+import { Component } from '../component'
+import { warn } from '../warning'
+
+const memoizeMap = new WeakMap()
+
+export function memoize(
+ getter: () => any,
+ instance: Component,
+ id: number,
+ keys?: any[]
+): any {
+ if (__DEV__ && !Array.isArray(keys)) {
+ warn(
+ `keys passed to v-memo or memoize must be an array. Got ${String(keys)}`
+ )
+ }
+ let storage = memoizeMap.get(instance)
+ if (!storage) {
+ storage = []
+ memoizeMap.set(instance, storage)
+ }
+ const record = storage[id]
+ if (!record) {
+ const value = getter()
+ storage[id] = [value, keys]
+ return value
+ } else {
+ const [prevValue, prevKeys] = record
+ record[1] = keys
+ if (keys) {
+ for (let i = 0; i < keys.length; i++) {
+ if (keys[i] !== prevKeys[i]) {
+ return (record[0] = getter())
+ }
+ }
+ }
+ return prevValue
+ }
+}