feat: skip constant trees and memoize fn
This commit is contained in:
parent
d8cda2387f
commit
131936f144
@ -7,7 +7,6 @@ import {
|
||||
MountedVNode,
|
||||
RenderNode,
|
||||
createTextVNode,
|
||||
cloneVNode,
|
||||
Ref,
|
||||
VNodeChildren
|
||||
} from './vdom'
|
||||
@ -135,10 +134,6 @@ export function createRenderer(options: RendererOptions) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -346,6 +341,11 @@ export function createRenderer(options: RendererOptions) {
|
||||
contextVNode: MountedVNode | null,
|
||||
isSVG: boolean
|
||||
) {
|
||||
if (prevVNode === nextVNode) {
|
||||
nextVNode.el = prevVNode.el
|
||||
return
|
||||
}
|
||||
|
||||
const nextFlags = nextVNode.flags
|
||||
const prevFlags = prevVNode.flags
|
||||
|
||||
@ -768,19 +768,12 @@ export function createRenderer(options: RendererOptions) {
|
||||
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++) {
|
||||
@ -810,9 +803,6 @@ export function createRenderer(options: RendererOptions) {
|
||||
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++
|
||||
@ -828,9 +818,6 @@ export function createRenderer(options: RendererOptions) {
|
||||
|
||||
// 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--
|
||||
@ -849,11 +836,7 @@ export function createRenderer(options: RendererOptions) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -896,9 +879,6 @@ export function createRenderer(options: RendererOptions) {
|
||||
} else {
|
||||
pos = j
|
||||
}
|
||||
if (nextVNode.el) {
|
||||
nextChildren[j] = nextVNode = cloneVNode(nextVNode)
|
||||
}
|
||||
patch(prevVNode, nextVNode, container, contextVNode, isSVG)
|
||||
patched++
|
||||
break
|
||||
@ -940,9 +920,6 @@ export function createRenderer(options: RendererOptions) {
|
||||
} else {
|
||||
pos = j
|
||||
}
|
||||
if (nextVNode.el) {
|
||||
nextChildren[j] = nextVNode = cloneVNode(nextVNode)
|
||||
}
|
||||
patch(prevVNode, nextVNode, container, contextVNode, isSVG)
|
||||
patched++
|
||||
} else if (!canRemoveWholeContent) {
|
||||
@ -971,9 +948,6 @@ export function createRenderer(options: RendererOptions) {
|
||||
if (sources[i] === 0) {
|
||||
pos = i + nextStart
|
||||
nextVNode = nextChildren[pos]
|
||||
if (nextVNode.el) {
|
||||
nextChildren[pos] = nextVNode = cloneVNode(nextVNode)
|
||||
}
|
||||
nextPos = pos + 1
|
||||
mount(
|
||||
nextVNode,
|
||||
@ -1002,9 +976,6 @@ export function createRenderer(options: RendererOptions) {
|
||||
if (sources[i] === 0) {
|
||||
pos = i + nextStart
|
||||
nextVNode = nextChildren[pos]
|
||||
if (nextVNode.el) {
|
||||
nextChildren[pos] = nextVNode = cloneVNode(nextVNode)
|
||||
}
|
||||
nextPos = pos + 1
|
||||
mount(
|
||||
nextVNode,
|
||||
@ -1119,8 +1090,8 @@ export function createRenderer(options: RendererOptions) {
|
||||
} else {
|
||||
platformRemoveChild(container, el)
|
||||
}
|
||||
;(vnode as any).el = null
|
||||
}
|
||||
;(vnode as any).el = null
|
||||
}
|
||||
|
||||
function removeChildren(
|
||||
@ -1394,9 +1365,6 @@ export function createRenderer(options: RendererOptions) {
|
||||
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)
|
||||
|
53
packages/runtime-core/src/optional/memoize.ts
Normal file
53
packages/runtime-core/src/optional/memoize.ts
Normal file
@ -0,0 +1,53 @@
|
||||
// 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
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user