记一次keepAlive踩坑之旅
2019-06-20 本文已影响0人
sphenginx
缘起
现有个vue项目, 某些页面需要缓存。 于是加了 keep-alive
, 需要缓存的 router 放在 keep-alive 标签内。
标签如下:
<keep-alive :max="20">
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
后来增加了需求, 某些页面进入 A 的时候需要缓存, 某些页面进入 A 页面的时候需要重新render页面。
这时候需要 watch $route
的 from 和 to , 附实现代码如下:
watch: {
'$route'(to, from) {
const reInitList = ['trade', 'ha', 'deal'];
if(reInitList.includes(from.name) && this.$route.name == 'xxx') {
this.init();
}
}
}
后来发现,在需要 re init 页面的时候,发现参数读的是之前缓存的参数,并不是当前页面的参数信息。
后来在 vue 的 issue发现大家都有这样的痛点:
https://github.com/vuejs/vue/issues/6509
性空
后来查询 keep-alive 源码发现 render 的时候 有个 key,如果为空就会读取 cid:
render () {
const slot = this.$slots.default
const vnode: VNode = getFirstComponentChild(slot)
const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
if (componentOptions) {
// check pattern
const name: ?string = getComponentName(componentOptions)
const { include, exclude } = this
if (
// not included
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(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 (#3269)
? 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)
} 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)
}
}
vnode.data.keepAlive = true
}
return vnode || (slot && slot[0])
}
}
于是考虑 可以把 参数信息当做key的一部分来管理,这样就不会有参数被缓存的问题了。那么 keep-alive标签可以这么写:
<keep-alive :max="20">
<router-view v-if="$route.meta.keepAlive" :key="$route.fullPath"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
大功告成。