prune
function pruneCache (keepAliveInstance: any, filter: Function) {
const { cache, keys, _vnode } = keepAliveInstance
for (const key in cache) {
const cachedNode: ?VNode = cache[key]
if (cachedNode) { //已经缓存的node
const name: ?string = getComponentName(cachedNode.componentOptions)
if (name && !filter(name)) { // 缓存的node 不需要了
//修剪缓存实例,干掉缓存实体
pruneCacheEntry(cache, key, keys, _vnode)
}
}
}
}
include 类型: [String, RegExp, Array]
watch: {
include (val: string | RegExp | Array<string>) {
pruneCache(this, name => matches(val, name))
},
exclude (val: string | RegExp | Array<string>) {
pruneCache(this, name => !matches(val, name))
}
},
created () {
this.cache = Object.create(null)
this.keys = []
},
如何干掉缓存实体
function pruneCacheEntry (
cache: VNodeCache,
key: string,
keys: Array<string>, 来自keep-alive 组件
current?: VNode 来自keep-alive 组件
) {
const cached = cache[key]
if (cached && cached !== current) {
cached.componentInstance.$destroy() //干掉组件
}
cache[key] = null // cache 中置空 为什么不直接delete 呢
remove(keys, key) // 从keys 中删除key
}
render
const vnode: VNode = getFirstComponentChild(this.$slots.default)
<<< 回溯下
export function getFirstComponentChild (children: ?Array<VNode>): ?VNode {
if (Array.isArray(children)) {
for (let i = 0; i < children.length; i++) {
const c = children[i]
if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
return c
}
}
}
}
>>>
//找第一个组件
const vnode: VNode = getFirstComponentChild(this.$slots.default)
const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
if (componentOptions) {
// check pattern
const name: ?string = getComponentName(componentOptions)
//这个组件不需要缓存
if (name && (
(this.include && !matches(this.include, name)) ||
(this.exclude && matches(this.exclude, name))
)) {
return vnode
}
const { cache, keys } = this
const key: ?string = vnode.key == null
// same constructor may get registered as different local components
// so cid alone is not enough (
? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.key
if (cache[key]) { //缓存过了
vnode.componentInstance = cache[key].componentInstance
// make current key freshest
remove(keys, key)
keys.push(key) // 把key 放到keys 的最后面(lru : old --->latest )
} else { //没缓存
cache[key] = vnode
keys.push(key)
// prune oldest entry
// 触发max 限制了, 要把keys中的第一个干掉
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
}
vnode.data.keepAlive = true
}
return vnode