keep-alive的源码不到两百行,比较简单,这里做一个简单的源码分析 vue/src/component/keep-alive.js keep-alive允许传入include,exclude,以及max缓存的最大数量
props: {
include: patternTypes,
exclude: patternTypes,
max: [String, Number]
},
在初始化时,定义一个cache对象和一个keys数组
created () {
this.cache = Object.create(null)
this.keys = []
},
渲染时,获取默认插槽,得到插槽的vnode以及组件配置
render () {
const slot = this.$slots.default
const vnode: VNode = getFirstComponentChild(slot)
const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
if (componentOptions) {
const name: ?string = getComponentName(componentOptions)
const { include, exclude } = this
if (
(include && (!name || !matches(include, name))) ||
(exclude && name && matches(exclude, name))
) {
return vnode
}
const { cache, keys } = this
const key: ?string = vnode.key == null
? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.key
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance
remove(keys, key)
keys.push(key)
} else {
this.vnodeToCache = vnode
this.keyToCache = key
}
vnode.data.keepAlive = true
}
return vnode || (slot && slot[0])
}
在keep-alive组件中第一个method方法,cacheVNode 这个函数的功能就是判断vnodeToCache是否存在,存在就将对应的vnode保存到cache中,key保存到keys中
cacheVNode() {
const { cache, keys, vnodeToCache, keyToCache } = this
if (vnodeToCache) {
const { tag, componentInstance, componentOptions } = vnodeToCache
cache[keyToCache] = {
name: getComponentName(componentOptions),
tag,
componentInstance,
}
keys.push(keyToCache)
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
this.vnodeToCache = null
}
}
上面的createVNode的执行时机在mounted和updated的,就是说只有挂载时或者更新时才会有机会更新缓存的vnode
mounted () {
this.cacheVNode()
this.$watch('include', val => {
pruneCache(this, name => matches(val, name))
})
this.$watch('exclude', val => {
pruneCache(this, name => !matches(val, name))
})
},
updated () {
this.cacheVNode()
},
|