}
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]) {
//查看cache对象中已经缓存了该组件,则vnode直接使用缓存中的组件实例
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])
}
上述代码主要是在render函数中对是否是缓存渲染进行判断
vue keep-alive内部实现的基本流程就是:
首先通过getFirstComponentChild获取到内部的子组件
然后拿到该组件的name与keep-alive组件上定义的include与exclude属性进行匹配,
如果不匹配就表示不缓存组件,就直接返回该组件的vnode(vnode就是一个虚拟的dom树结构,由于原生dom上的属性非常多,消耗巨大,使用这种模拟方式会减少很多dom操作的开销)
如果匹配到,则在cache对象中查看是否已经缓存过该实例,如果有就直接将缓存的vnode的componentInstance(组件实例)覆盖到目前的vnode上面,否则将vnode存储在cache中。
React中的解决方案
在react中没有提供类似于vue的keep-alive的解决方案,这意味这我们可能需要自己编写一些代码或者通过一些第三方的模块来解决。
在React项目GitHub的该issue中进行了相关讨论,开发维护人员给出了两种方式来解决:
将数据与组件分开缓存。例如,你可以将state提升到一个不会被卸载的父级组件,或者像redux一样将其放在一个侧面缓存中。我们也正在为此开发一类的API支持(context)。
不要去卸载你要“保持活动”的视图,只需使用style={{display:’none’}}属性去隐藏它们。

1. 集中的状态管理恢复快照方式
在React中通过redux或mobx集中的状态管理来缓存页面数据以及滚动条等信息,以达到缓存页面的效果。
componentDidMount() {
const {app: {dataSoruce = [], scrollTop}, loadData} = this.props;
if (dataSoruce.length) { //判断redux中是否已经有数据源
// 有数据则不再加载收据,只恢复滚动状态
window.scrollTo(0, scrollTop);










