为什么需要缓存
总的来说是为了提高用户体验。如下图所示,当选中“家具厨具”后,进入其它页面返回后我们希望选中的还是“家具厨具”,并且停留在原来浏览的位置。
Vue应用在切换路由后原页面的组件会被销毁,后退时会重新渲染组件,原页面运行中产生的数据会全部丢失。为了达到缓存的目的,Vue提供了keep-alive内置组件。
keep-alive
keep-alive会缓存不活动的组件实例,用keep-alive包裹router-view就可以缓存页面。
<keep-alive >
<router-view :key="$route.fullPath" />
</keep-alive>
这样做会简单粗暴地把所有页面都缓存起来,我们想要的是进入新页面时重新渲染新页面组件,返回上一页面时使用缓存。所以在切换路由时,需要判断是进入新页面还是返回上一个页面,在路由元信息中定义页面之间的层级关系:
{
path: 'staff-performance',
component: () => import('@/views/dashboard/merchant/home/department/staff-performance/index'),
props: true,
meta: { title: '员工业绩', level: 4 }
}
通过比较level的大小就可以判断是进入新页面还是返回上一个页面,如level: 1 => level: 2是进入新页面,level: 3 => level: 2是返回上一个页面。
删除缓存
返回上一个页面时需要销毁新页面,而Vue没有提供手动删除keep-alive缓存的方法。参考动态移除缓存我们可以新建一个page-cache.js文件,定义mixin:
export default {
beforeRouteLeave(to, from, next) {
// 判断是否返回上一页面, 返回上一页面要清除缓存(level: 页面层级,在router.js中配置) 参考https://segmentfault.com/a/1190000015845117
if (from && from.meta.level && to.meta.level && from.meta.level > to.meta.level) {
if (this.$vnode && this.$vnode.data.keepAlive) {
if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache) {
if (this.$vnode.componentOptions) {
const key = this.$vnode.key == null
? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
: this.$vnode.key
const cache = this.$vnode.parent.componentInstance.cache
const keys = this.$vnode.parent.componentInstance.keys
if (cache[key]) {
if (keys.length) {
const index = keys.indexOf(key)
if (index > -1) {
keys.splice(index, 1)
}
}
delete cache[key]
}
}
}
}
this.$destroy()
}
next()
}
}
只缓存部分页面
缓存部分页面需要修改一下router-view和keep-alive的写法
<keep-alive >
<router-view v-if="$route.meta.keepAlive" :key="$route.fullPath" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" :key="$route.fullPath" />
是否开启缓存在路由元信息中配置
{
path: 'staff-performance',
component: () => import('@/views/dashboard/merchant/home/department/staff-performance/index'),
props: true,
meta: { title: '员工业绩', keepAlive: true, level: 4 }
}
注意
嵌套路由需要将keep-alive包裹在最内层的router-view外面,否则页面无法缓存。
优化
所有需要缓存的页面都需要定义一次mixin,比较繁琐。定义为全局mixin,在返回上一个页面时,部分组件不销毁,待优化。
总结
第一步:在路由元信息中定义页面层级以及是否需要缓存
第二步:在需要缓存的组件引入page-cache.js作为mixin