keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件中。
用keep-alive包裹的路由页面路由地址不改变时,组件实例不会被销毁
使用场景:
例如有一个商品页面和一个详情页面,这样在两个页面切换的时候就可以用到keep-alive包裹,再切换到详情的时候,把商品页状态位置保留在内存中,没有销毁,(自身不会生成dom元素)等从详情返回的时候,页面还是之前的状态,更一步优化了性能,
优点:
优点是在组件切换过程中,把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性,
缓存的方式有几种:
一、如果需要缓存整个项目,直接在app.vue中用keep-alive包裹router-view即可。
二、需要缓存部分页面 (2种方法)
方法1、
如果缓存部分页面,第一种是使用使用新增属性include/exclude,缓存部分页面,首先在data中定义,isKeep:[‘组件1’,‘组件2’],在keepAlive上用::include="iskeep",注意一定要在路由和被缓存的组件加上name否则缓存会失效,如果缓存页面较少,可以直接 include="UserDetail,BoxDataManagement"
————————————————
后台管理项目中 使用:layout/components/AppMain.vue <keep-alive :include="">
不会触发created和mounted
会触发activated和deactivated
activated:keep-alive组件激活时调用
deactivated:keep-alive组件停用时调用
例如
AppMain.vue页面
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<keep-alive include="UserDetail,BoxDataManagement"> // 页面缓存 [XSea 2022.4.21]
<router-view :key="key" />
</keep-alive>
</transition>
</section>
</template>
<script>
export default {
name: 'AppMain',
computed: {
key() {
return this.$route.path
}
}
}
</script>
// 离开页面设置缓存
beforeRouteLeave(to, from, next) {
// 去哪些页面缓存本页
if (to.name == 'BoxProductDetails') {
// 开启缓存
from.meta.keepAlive = true
console.log('from true:' + from.name)
console.log('beforeRouteLeave keepAlive:' + from.meta.keepAlive)
} else {
// 关闭缓存
from.meta.keepAlive = false
console.log('from false:' + from.name)
console.log('beforeRouteLeave keepAlive:' + from.meta.keepAlive)
}
next()
},
activated() {
console.log('activated enter keepAlive:' + this.$route.meta.keepAlive)
if (!this.$route.meta.keepAlive) {
// 重置页面
this.tableData = []
this.options = []
this.restaurants = []
this.form.startTime = ''
this.form.endTime = ''
this.form.boxName = ''
this.form.boxId = ''
this.init()
// 重置页面位置
window.scrollTo(0, 1)
} else {
if (this.scrollTop > 0) {
window.scrollTo(0, this.scrollTop)
this.scrollTop = 0
}
}
window.addEventListener('scroll', this.handleScroll)
// 通过这个控制刷新
this.$route.meta.keepAlive = false
console.log('activated leave keepAlive:' + this.$route.meta.keepAlive)
},
deactivated() {
window.removeEventListener('scroll', this.handleScroll)
},
在商品页面添加路由钩子,做逻辑判断等
关于子路由的页面缓存,可以添加 activeMenu
原本选中是根据is-active来判断的,但是进图子路由都没有这个选中了,这时候只需要在再路由的meta中添加activeMenu
如 子路由是/DataManagement/BoxDataManagement/BoxProductDetails
就可以用 activeMenu: '/DataManagement/BoxDataManagement'
// 盲盒统计管理
{
path: 'BoxDataManagement',
name: 'BoxDataManagement',
component: () => import('@/views/DataManagement/BoxDataManagement/BoxDataManagement'),
meta: {
title: '盲盒数据统计',
icon: 'el-icon-document',
permissions: ['menu_data_box_report']
}
},
// 盲盒商品详情
{
path: 'BoxProductDetails',
name: 'BoxProductDetails',
hidden: true,
component: () => import('@/views/DataManagement/BoxDataManagement/BoxProductDetails/BoxProductDetails'),
meta: {
title: '商品详情',
icon: 'el-icon-document',
activeMenu: '/DataManagement/BoxDataManagement'
}
},
如新加一个 页面(商品页面+商品详情页)
左侧页面为商品页,右侧为路由页面
即可实现页面缓存,从详情返回的时候,商品详情页还是在跳详情之前的状态
方法2、
第二种是结合Router,router/index.js中通过设置路由元信息,指定属性缓存属性值为true,不缓存属性值为fasle,在app.vue中用keepAlive包裹要缓存的router-view,通过$router.meta.设置的路由原信息属性值获取,在keepAlive外在用v-if取反判断,v-if和v-else不是配套使用,为什么不使用v-else,因为v-if和v-else之间要挨着使用不然会报错
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive">
</router-view>
在router.js中,对需要缓存 的页面设置
meta: {
keepAlive: true
}