Vue 的 keep-alive 是一个抽象组件,用于缓存动态组件或组件树,以减少组件的重复渲染。使用 keep-alive 可以提高应用的性能。接下来介绍下使用keep-alive的两个场景。
场景1:打开一个A页签页面,填写表单数据后切换到B页签,再回到A页签页面时刚刚填写的数据没有了,这时候想要在切换页签时保持页面状态就可以简单的使用以下方法来实现:
使用 keep-alive 很简单,只需要在需要缓存的组件外包裹一个 <keep-alive> 标签,如下所示:
注意:只有在配置了组件的 name 属性时才会生效,这是因为 keep-alive 组件会使用这个 name 属性来缓存组件实例。如果组件没有配置 name 属性,那么 keep-alive 组件就无法缓存组件实例,也就无法实现缓存的效果
<keep-alive>
<router-view/>
</keep-alive>
场景2:想要动态的控制页签的缓存,也就是在页签导航栏切换页签的时候不改变页面的状态,但是在右键刷新页签或关闭页签重新从左边菜单栏打开页签的时候,希望能够重新加载新页面。
解决方法:
1. 在路由配置中给要缓存的页面添加mata配置,自定义一个缓存标志keepAlive:
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
name: 'Dashboard',
meta: {
title: '首页',
icon: 'dashboard',
keepAlive: true
}
}
]
}
2. 用vuex store存储一个全局变量cachedViews,代表当前打开的页签中要keepAlive缓存的页面,在添加/关闭/刷新页签导航栏时,要同步更新cachedViews (cachedViews的操作这里不做具体展示)
3. 注册监听全局的removeCachePage方法(可在其他组件中触发此方法):通过操作<keep-alive>组件内部的缓冲数据cache、keys来动态控制页面缓存(手动删除指定页面的缓存):
(注意:这里transition 标签只能包含1个元素)
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in" >
<keep-alive>
<router-view ref="routerView" v-if="$route.meta.keepAlive" :key='$route.path'/>
</keep-alive>
</transition>
<transition name="fade-transform" mode="out-in" >
<router-view ref="routerView" :key='$route.path' v-if="!$route.meta.keepAlive" />
</transition>
</section>
</template>
<script>
import Bus from "@/utils/bus"
export default {
name: 'AppMain',
mounted() {
this.$nextTick(() => {
Bus.$on('removeCachePage', key => {
if(!this.$refs.routerView){
return
}
/**
* @param {Object} cache:类数组对象,存放缓冲的路由组件,键值对形,key为路由路径,value为路由组件Vnode
* @param {Array} keys:数组,存放缓冲的路由组件的key,即路由路径
* @param {String} key:字符串,路由组件的key,指定要删除的路由组件key值(路由组件的路径path)
*/
const { cache, keys } = this.$refs.routerView.$vnode.parent.componentInstance
let index = keys.findIndex(item => {
let i = item.indexOf("/")
return item.slice(i) == key
})
index != -1 &&
(() => {
// 移除对应页面缓冲
delete cache[keys[index]]
keys.splice(index, 1)
console.log('删除缓冲页面成功~', 'color:red')
})()
})
})
},
beforeDestroy() {
Bus.$off('removeCachePage')
}
}
</script>
cache 和 keys 的数据结构如下:
4. 在全局路由守卫router.beforeEach中添加判断:进入页面前,将不在cachedViews中的页面的缓存组件删除掉,从而可以重新渲染新的页面: