原理
在 created 函数调用时将需要缓存的 VNode 节点保存在 this.cache 中/在 render(页面渲染) 时,如果 VNode 的 name 符合缓存条件(可以用 include 以及 exclude 控制),则会从 this.cache 中取出之前缓存的 VNode 实例进行渲染。
VNode:虚拟DOM,其实就是一个JS对象
生命周期函数
activated
在 keep-alive 组件激活时调用
该钩子函数在服务器端渲染期间不被调用
deactivated
在 keep-alive 组件停用时调用
该钩子在服务器端渲染期间不被调用
被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated 与 deactivated
使用 keep-alive 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在 activated 阶段获取数据,承担原来 created 钩子函数中获取数据的任务。
注意: 只有组件被 keep-alive 包裹时,这两个生命周期函数才会被调用,如果作为正常组件使用,是不会被调用的,以及在 2.1.0 版本之后,使用 exclude 排除之后,就算被包裹在 keep-alive 中,这两个钩子函数依然不会被调用!另外,在服务端渲染时,此钩子函数也不会被调用。
实现目的
假设有A,B,C三个页面, A > B > C 的流程下: 页面不缓存, C > B > A 的流程下: B页面进行缓存。
实现步骤
- 路由的配置:
router.js:
routes: [
{
path: '/',
component: A,
name: A
},
{
path: '/b',
component: B,
name: B,
meta: {
keepAlive: true, // 需要被缓存
isBack: false // 用来判断是否后退
}
},
{
path: '/c',
component: C,
name: C
}
]
router.beforeEach((to, from, next) => {
let list = ['B'] // 存放需要缓存页面路由的name值
if (list.indexOf(to.name) > -1) {
to.meta.keepAlive = true
}
next()
})
- B页面(需要被缓存的页面)
mounted () {
this.getData()
},
activated() {
if(!this.$route.meta.isBack) {
// 如果isBack是false,表明需要获取新数据,否则就不再请求,直接使用缓存的数据
this.getData()
}
// 恢复成默认的false,避免isBack一直是true,导致下次无法获取数据
this.$route.meta.isBack = false
},
beforeRouteEnter(to, from, next) {
//判断是从哪个路由过来的,若是C页面不需要刷新获取新数据,直接用之前缓存的数据即可
if(from.name === 'C') {
to.meta.isBack = true;
}
next();
},
beforeRouteLeave (to, from, next) {
// 回到A页面,并销毁keep-live
if (to.name === 'A' && this.$route.meta.isBack) {
from.mate.keepAlive = false
this.$destroy()
}
next()
}