From b694d93c530d078b4d065437842b9b0f8c42da59 Mon Sep 17 00:00:00 2001 From: zrh122 <1229550935@qq.com> Date: Wed, 1 May 2019 08:00:25 +0800 Subject: [PATCH] refactor(keep-alive): cache what is really needed not the whole VNode data --- src/core/components/keep-alive.js | 51 +++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/core/components/keep-alive.js b/src/core/components/keep-alive.js index fb4cf1e883b..a601260ffee 100644 --- a/src/core/components/keep-alive.js +++ b/src/core/components/keep-alive.js @@ -3,7 +3,13 @@ import { isRegExp, remove } from 'shared/util' import { getFirstComponentChild } from 'core/vdom/helpers/index' -type VNodeCache = { [key: string]: ?VNode }; +type CacheEntry = { + name: ?string; + tag: ?string; + componentInstance: Component; +}; + +type CacheEntryMap = { [key: string]: ?CacheEntry }; function getComponentName (opts: ?VNodeComponentOptions): ?string { return opts && (opts.Ctor.options.name || opts.tag) @@ -24,9 +30,9 @@ function matches (pattern: string | RegExp | Array, name: string): boole function pruneCache (keepAliveInstance: any, filter: Function) { const { cache, keys, _vnode } = keepAliveInstance for (const key in cache) { - const cachedNode: ?VNode = cache[key] - if (cachedNode) { - const name: ?string = getComponentName(cachedNode.componentOptions) + const entry: ?CacheEntry = cache[key] + if (entry) { + const name: ?string = entry.name if (name && !filter(name)) { pruneCacheEntry(cache, key, keys, _vnode) } @@ -35,14 +41,14 @@ function pruneCache (keepAliveInstance: any, filter: Function) { } function pruneCacheEntry ( - cache: VNodeCache, + cache: CacheEntryMap, key: string, keys: Array, current?: VNode ) { - const cached = cache[key] - if (cached && (!current || cached.tag !== current.tag)) { - cached.componentInstance.$destroy() + const entry: ?CacheEntry = cache[key] + if (entry && (!current || entry.tag !== current.tag)) { + entry.componentInstance.$destroy() } cache[key] = null remove(keys, key) @@ -72,6 +78,10 @@ export default { }, mounted () { + if (this.putEntry) { + this.putEntry() + this.putEntry = null + } this.$watch('include', val => { pruneCache(this, name => matches(val, name)) }) @@ -80,6 +90,13 @@ export default { }) }, + updated () { + if (this.putEntry) { + this.putEntry() + this.putEntry = null + } + }, + render () { const slot = this.$slots.default const vnode: VNode = getFirstComponentChild(slot) @@ -109,11 +126,19 @@ export default { remove(keys, key) keys.push(key) } else { - cache[key] = vnode - keys.push(key) - // prune oldest entry - if (this.max && keys.length > parseInt(this.max)) { - pruneCacheEntry(cache, keys[0], keys, this._vnode) + // put entry until component is instantiated + this.putEntry = () => { + const { tag, componentInstance } = vnode + cache[key] = { + name, + tag, + componentInstance + } + keys.push(key) + // prune oldest entry + if (this.max && keys.length > parseInt(this.max)) { + pruneCacheEntry(cache, keys[0], keys, this._vnode) + } } }